last error remaining

This commit is contained in:
Priec
2025-09-18 18:53:55 +02:00
parent 1f6dc3cd75
commit 49277cfdd4
6 changed files with 278 additions and 241 deletions

View File

@@ -3,6 +3,7 @@
use crate::common::setup_isolated_db; use crate::common::setup_isolated_db;
use server::table_script::handlers::post_table_script::post_table_script; // Fixed import use server::table_script::handlers::post_table_script::post_table_script; // Fixed import
use common::proto::komp_ac::table_script::PostTableScriptRequest; use common::proto::komp_ac::table_script::PostTableScriptRequest;
use common::proto::komp_ac::table_definition::ColumnDefinition;
use rstest::*; use rstest::*;
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
@@ -12,15 +13,10 @@ async fn create_test_table(
pool: &PgPool, pool: &PgPool,
schema_id: i64, schema_id: i64,
table_name: &str, table_name: &str,
columns: Vec<(&str, &str)>, columns: Vec<ColumnDefinition>,
) -> i64 { ) -> i64 {
let column_definitions: Vec<String> = columns let columns_json = serde_json::to_value(columns).unwrap();
.iter() let indexes_json = serde_json::json!([]);
.map(|(name, type_def)| format!("\"{}\" {}", name, type_def))
.collect();
let columns_json = json!(column_definitions);
let indexes_json = json!([]);
sqlx::query_scalar!( sqlx::query_scalar!(
r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes) r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes)
@@ -115,22 +111,17 @@ async fn test_comprehensive_error_scenarios(
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create comprehensive error test table // Create comprehensive error test table
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
// Valid types ColumnDefinition { name: "valid_numeric".into(), field_type: "NUMERIC(10, 2)".into() },
("valid_numeric", "NUMERIC(10, 2)"), ColumnDefinition { name: "valid_integer".into(), field_type: "INTEGER".into() },
("valid_integer", "INTEGER"), ColumnDefinition { name: "text_col".into(), field_type: "TEXT".into() },
ColumnDefinition { name: "boolean_col".into(), field_type: "BOOLEAN".into() },
// Invalid for math operations ColumnDefinition { name: "bigint_col".into(), field_type: "BIGINT".into() },
("text_col", "TEXT"), ColumnDefinition { name: "date_col".into(), field_type: "DATE".into() },
("boolean_col", "BOOLEAN"), ColumnDefinition { name: "timestamp_col".into(), field_type: "TIMESTAMPTZ".into() },
("bigint_col", "BIGINT"), ColumnDefinition { name: "bigint_target".into(), field_type: "BIGINT".into() },
("date_col", "DATE"), ColumnDefinition { name: "date_target".into(), field_type: "DATE".into() },
("timestamp_col", "TIMESTAMPTZ"), ColumnDefinition { name: "timestamp_target".into(), field_type: "TIMESTAMPTZ".into() },
// Invalid target types
("bigint_target", "BIGINT"),
("date_target", "DATE"),
("timestamp_target", "TIMESTAMPTZ"),
]; ];
let table_id = create_test_table(&pool, schema_id, "error_table", columns).await; let table_id = create_test_table(&pool, schema_id, "error_table", columns).await;
@@ -169,7 +160,9 @@ async fn test_malformed_script_scenarios(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("result", "NUMERIC(10, 2)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition { name: "result".into(), field_type: "NUMERIC(10, 2)".into() }
];
let table_id = create_test_table(&pool, schema_id, "malformed_test", columns).await; let table_id = create_test_table(&pool, schema_id, "malformed_test", columns).await;
let request = PostTableScriptRequest { let request = PostTableScriptRequest {
@@ -194,7 +187,9 @@ async fn test_advanced_validation_scenarios(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("result", "NUMERIC(10, 2)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition { name: "result".into(), field_type: "NUMERIC(10, 2)".into() }
];
let table_id = create_test_table(&pool, schema_id, "advanced_test", columns).await; let table_id = create_test_table(&pool, schema_id, "advanced_test", columns).await;
let request = PostTableScriptRequest { let request = PostTableScriptRequest {
@@ -236,16 +231,16 @@ async fn test_dependency_cycle_detection() {
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create table_b first // Create table_b first
let table_b_columns = vec![ let table_b_columns: Vec<ColumnDefinition> = vec![
("value_b", "NUMERIC(10, 2)"), ColumnDefinition { name: "value_b".into(), field_type: "NUMERIC(10, 2)".into() },
("result_b", "NUMERIC(10, 2)"), ColumnDefinition { name: "result_b".into(), field_type: "NUMERIC(10, 2)".into() },
]; ];
let table_b_id = create_test_table(&pool, schema_id, "table_b", table_b_columns).await; let table_b_id = create_test_table(&pool, schema_id, "table_b", table_b_columns).await;
// Create table_a // Create table_a
let table_a_columns = vec![ let table_a_columns: Vec<ColumnDefinition> = vec![
("value_a", "NUMERIC(10, 2)"), ColumnDefinition { name: "value_a".into(), field_type: "NUMERIC(10, 2)".into() },
("result_a", "NUMERIC(10, 2)"), ColumnDefinition { name: "result_a".into(), field_type: "NUMERIC(10, 2)".into() },
]; ];
let table_a_id = create_test_table(&pool, schema_id, "table_a", table_a_columns).await; let table_a_id = create_test_table(&pool, schema_id, "table_a", table_a_columns).await;
@@ -305,7 +300,9 @@ async fn test_edge_case_identifiers(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("result", "NUMERIC(10, 2)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition { name: "result".into(), field_type: "NUMERIC(10, 2)".into() }
];
let table_id = create_test_table(&pool, schema_id, "identifier_test", columns).await; let table_id = create_test_table(&pool, schema_id, "identifier_test", columns).await;
// Test with edge case identifier in script // Test with edge case identifier in script
@@ -342,7 +339,9 @@ async fn test_sql_injection_prevention() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("result", "NUMERIC(10, 2)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition { name: "result".into(), field_type: "NUMERIC(10, 2)".into() }
];
let table_id = create_test_table(&pool, schema_id, "injection_test", columns).await; let table_id = create_test_table(&pool, schema_id, "injection_test", columns).await;
// Attempt SQL injection through script content // Attempt SQL injection through script content
@@ -388,9 +387,9 @@ async fn test_performance_with_deeply_nested_expressions() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("x", "NUMERIC(15, 8)"), ColumnDefinition { name: "x".into(), field_type: "NUMERIC(15, 8)".into() },
("performance_result", "NUMERIC(25, 12)"), ColumnDefinition { name: "performance_result".into(), field_type: "NUMERIC(25, 12)".into() },
]; ];
let table_id = create_test_table(&pool, schema_id, "performance_test", columns).await; let table_id = create_test_table(&pool, schema_id, "performance_test", columns).await;
@@ -437,11 +436,11 @@ async fn test_concurrent_script_creation() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("value", "NUMERIC(10, 2)"), ColumnDefinition { name: "value".into(), field_type: "NUMERIC(10, 2)".into() },
("result1", "NUMERIC(10, 2)"), ColumnDefinition { name: "result1".into(), field_type: "NUMERIC(10, 2)".into() },
("result2", "NUMERIC(10, 2)"), ColumnDefinition { name: "result2".into(), field_type: "NUMERIC(10, 2)".into() },
("result3", "NUMERIC(10, 2)"), ColumnDefinition { name: "result3".into(), field_type: "NUMERIC(10, 2)".into() },
]; ];
let table_id = create_test_table(&pool, schema_id, "concurrent_test", columns).await; let table_id = create_test_table(&pool, schema_id, "concurrent_test", columns).await;
@@ -500,9 +499,10 @@ async fn test_error_message_localization_and_clarity() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![
("text_col", "TEXT"), let columns: Vec<ColumnDefinition> = vec![
("result", "NUMERIC(10, 2)"), ColumnDefinition { name: "text_col".into(), field_type: "TEXT".into() },
ColumnDefinition { name: "result".into(), field_type: "NUMERIC(10, 2)".into() },
]; ];
let table_id = create_test_table(&pool, schema_id, "error_clarity_test", columns).await; let table_id = create_test_table(&pool, schema_id, "error_clarity_test", columns).await;

View File

@@ -3,6 +3,7 @@
use crate::common::setup_isolated_db; use crate::common::setup_isolated_db;
use server::table_script::handlers::post_table_script::post_table_script; // Fixed import use server::table_script::handlers::post_table_script::post_table_script; // Fixed import
use common::proto::komp_ac::table_script::PostTableScriptRequest; use common::proto::komp_ac::table_script::PostTableScriptRequest;
use common::proto::komp_ac::table_definition::ColumnDefinition;
use rstest::*; use rstest::*;
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
@@ -12,15 +13,10 @@ async fn create_test_table(
pool: &PgPool, pool: &PgPool,
schema_id: i64, schema_id: i64,
table_name: &str, table_name: &str,
columns: Vec<(&str, &str)>, columns: Vec<ColumnDefinition>,
) -> i64 { ) -> i64 {
let column_definitions: Vec<String> = columns let columns_json = serde_json::to_value(columns).unwrap();
.iter() let indexes_json = serde_json::json!([]);
.map(|(name, type_def)| format!("\"{}\" {}", name, type_def))
.collect();
let columns_json = json!(column_definitions);
let indexes_json = json!([]);
sqlx::query_scalar!( sqlx::query_scalar!(
r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes) r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes)
@@ -97,7 +93,9 @@ async fn test_steel_decimal_literal_operations(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("result", "NUMERIC(30, 15)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(30, 15)".to_string() }
];
let table_id = create_test_table(&pool, schema_id, "literal_test", columns).await; let table_id = create_test_table(&pool, schema_id, "literal_test", columns).await;
let script = format!(r#"({} "{}" "{}")"#, operation, value1, value2); let script = format!(r#"({} "{}" "{}")"#, operation, value1, value2);
@@ -133,9 +131,9 @@ async fn test_steel_decimal_column_operations(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("test_value", column_type), ColumnDefinition { name: "test_value".to_string(), field_type: column_type.to_string() },
("result", "NUMERIC(30, 15)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(30, 15)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "column_test", columns).await; let table_id = create_test_table(&pool, schema_id, "column_test", columns).await;
@@ -179,12 +177,12 @@ async fn test_complex_financial_calculation(
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create a realistic financial calculation table // Create a realistic financial calculation table
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("principal", "NUMERIC(16, 2)"), // Principal amount ColumnDefinition { name: "principal".to_string(), field_type: "NUMERIC(16, 2)".to_string() }, // Principal amount
("annual_rate", "NUMERIC(6, 5)"), // Interest rate ColumnDefinition { name: "annual_rate".to_string(), field_type: "NUMERIC(6, 5)".to_string() }, // Interest rate
("years", "INTEGER"), // Time period ColumnDefinition { name: "years".to_string(), field_type: "INTEGER".to_string() }, // Time period
("compounding_periods", "INTEGER"), // Compounding frequency ColumnDefinition { name: "compounding_periods".to_string(), field_type: "INTEGER".to_string() }, // Compounding frequency
("compound_interest", "NUMERIC(20, 8)"), // Result ColumnDefinition { name: "compound_interest".to_string(), field_type: "NUMERIC(20, 8)".to_string() }, // Result
]; ];
let table_id = create_test_table(&pool, schema_id, "financial_calc", columns).await; let table_id = create_test_table(&pool, schema_id, "financial_calc", columns).await;
@@ -217,11 +215,11 @@ async fn test_scientific_precision_calculations() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("measurement_a", "NUMERIC(25, 15)"), ColumnDefinition { name: "measurement_a".to_string(), field_type: "NUMERIC(25, 15)".to_string() },
("measurement_b", "NUMERIC(25, 15)"), ColumnDefinition { name: "measurement_b".to_string(), field_type: "NUMERIC(25, 15)".to_string() },
("coefficient", "NUMERIC(10, 8)"), ColumnDefinition { name: "coefficient".to_string(), field_type: "NUMERIC(10, 8)".to_string() },
("scientific_result", "NUMERIC(30, 18)"), ColumnDefinition { name: "scientific_result".to_string(), field_type: "NUMERIC(30, 18)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "scientific_data", columns).await; let table_id = create_test_table(&pool, schema_id, "scientific_data", columns).await;
@@ -259,9 +257,9 @@ async fn test_precision_boundary_conditions(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("boundary_value", numeric_type), ColumnDefinition { name: "boundary_value".to_string(), field_type: numeric_type.to_string() },
("result", "NUMERIC(30, 15)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(30, 15)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "boundary_test", columns).await; let table_id = create_test_table(&pool, schema_id, "boundary_test", columns).await;
@@ -284,11 +282,11 @@ async fn test_mixed_integer_and_numeric_operations() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("integer_quantity", "INTEGER"), ColumnDefinition { name: "integer_quantity".to_string(), field_type: "INTEGER".to_string() },
("numeric_price", "NUMERIC(10, 4)"), ColumnDefinition { name: "numeric_price".to_string(), field_type: "NUMERIC(10, 4)".to_string() },
("numeric_tax_rate", "NUMERIC(5, 4)"), ColumnDefinition { name: "numeric_tax_rate".to_string(), field_type: "NUMERIC(5, 4)".to_string() },
("total_with_tax", "NUMERIC(15, 4)"), ColumnDefinition { name: "total_with_tax".to_string(), field_type: "NUMERIC(15, 4)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "mixed_types_calc", columns).await; let table_id = create_test_table(&pool, schema_id, "mixed_types_calc", columns).await;
@@ -325,9 +323,9 @@ async fn test_mathematical_edge_cases(
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("test_value", "NUMERIC(15, 6)"), ColumnDefinition { name: "test_value".to_string(), field_type: "NUMERIC(15, 6)".to_string() },
("result", "NUMERIC(20, 8)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(20, 8)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "edge_case_test", columns).await; let table_id = create_test_table(&pool, schema_id, "edge_case_test", columns).await;
@@ -381,10 +379,10 @@ async fn test_comparison_operations_with_valid_types() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("value_a", "NUMERIC(10, 2)"), ColumnDefinition { name: "value_a".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("value_b", "INTEGER"), ColumnDefinition { name: "value_b".to_string(), field_type: "INTEGER".to_string() },
("comparison_result", "BOOLEAN"), ColumnDefinition { name: "comparison_result".to_string(), field_type: "BOOLEAN".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "comparison_test", columns).await; let table_id = create_test_table(&pool, schema_id, "comparison_test", columns).await;
@@ -419,11 +417,11 @@ async fn test_nested_mathematical_expressions() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("x", "NUMERIC(15, 8)"), ColumnDefinition { name: "x".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("y", "NUMERIC(15, 8)"), ColumnDefinition { name: "y".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("z", "INTEGER"), ColumnDefinition { name: "z".to_string(), field_type: "INTEGER".to_string() },
("nested_result", "NUMERIC(25, 12)"), ColumnDefinition { name: "nested_result".to_string(), field_type: "NUMERIC(25, 12)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "nested_calc", columns).await; let table_id = create_test_table(&pool, schema_id, "nested_calc", columns).await;

View File

@@ -3,6 +3,7 @@
use crate::common::setup_isolated_db; use crate::common::setup_isolated_db;
use server::table_script::handlers::post_table_script::post_table_script; use server::table_script::handlers::post_table_script::post_table_script;
use common::proto::komp_ac::table_script::{PostTableScriptRequest, TableScriptResponse}; use common::proto::komp_ac::table_script::{PostTableScriptRequest, TableScriptResponse};
use common::proto::komp_ac::table_definition::ColumnDefinition;
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
@@ -26,14 +27,9 @@ impl TableScriptTestHelper {
} }
} }
pub async fn create_table_with_types(&self, table_name: &str, column_definitions: Vec<(&str, &str)>) -> i64 { pub async fn create_table_with_types(&self, table_name: &str, column_definitions: Vec<ColumnDefinition>) -> i64 {
let columns: Vec<String> = column_definitions let columns_json = serde_json::to_value(column_definitions).unwrap();
.iter() let indexes_json = serde_json::json!([]);
.map(|(name, type_def)| format!("\"{}\" {}", name, type_def))
.collect();
let columns_json = json!(columns);
let indexes_json = json!([]);
sqlx::query_scalar!( sqlx::query_scalar!(
r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes) r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes)
@@ -73,24 +69,24 @@ mod integration_tests {
"comprehensive_table", "comprehensive_table",
vec![ vec![
// Supported types for math operations // Supported types for math operations
("integer_col", "INTEGER"), ColumnDefinition { name: "integer_col".to_string(), field_type: "INTEGER".to_string() },
("numeric_basic", "NUMERIC(10, 2)"), ColumnDefinition { name: "numeric_basic".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("numeric_high_precision", "NUMERIC(28, 15)"), ColumnDefinition { name: "numeric_high_precision".to_string(), field_type: "NUMERIC(28, 15)".to_string() },
("numeric_currency", "NUMERIC(14, 4)"), ColumnDefinition { name: "numeric_currency".to_string(), field_type: "NUMERIC(14, 4)".to_string() },
// Supported but not for math operations // Supported but not for math operations
("text_col", "TEXT"), ColumnDefinition { name: "text_col".to_string(), field_type: "TEXT".to_string() },
("boolean_col", "BOOLEAN"), ColumnDefinition { name: "boolean_col".to_string(), field_type: "BOOLEAN".to_string() },
// Prohibited types entirely // Prohibited types entirely
("bigint_col", "BIGINT"), ColumnDefinition { name: "bigint_col".to_string(), field_type: "BIGINT".to_string() },
("date_col", "DATE"), ColumnDefinition { name: "date_col".to_string(), field_type: "DATE".to_string() },
("timestamp_col", "TIMESTAMPTZ"), ColumnDefinition { name: "timestamp_col".to_string(), field_type: "TIMESTAMPTZ".to_string() },
// Result columns of various types // Result columns of various types
("result_integer", "INTEGER"), ColumnDefinition { name: "result_integer".to_string(), field_type: "INTEGER".to_string() },
("result_numeric", "NUMERIC(15, 5)"), ColumnDefinition { name: "result_numeric".to_string(), field_type: "NUMERIC(15, 5)".to_string() },
("result_text", "TEXT"), ColumnDefinition { name: "result_text".to_string(), field_type: "TEXT".to_string() },
] ]
).await; ).await;
@@ -150,13 +146,13 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"precision_table", "precision_table",
vec![ vec![
("low_precision", "NUMERIC(5, 2)"), // e.g., 999.99 ColumnDefinition { name: "low_precision".to_string(), field_type: "NUMERIC(5, 2)".to_string() }, // e.g., 999.99
("medium_precision", "NUMERIC(10, 4)"), // e.g., 999999.9999 ColumnDefinition { name: "medium_precision".to_string(), field_type: "NUMERIC(10, 4)".to_string() }, // e.g., 999999.9999
("high_precision", "NUMERIC(28, 15)"), // Maximum PostgreSQL precision ColumnDefinition { name: "high_precision".to_string(), field_type: "NUMERIC(28, 15)".to_string() }, // Maximum PostgreSQL precision
("currency", "NUMERIC(14, 4)"), // Standard currency precision ColumnDefinition { name: "currency".to_string(), field_type: "NUMERIC(14, 4)".to_string() }, // Standard currency precision
("percentage", "NUMERIC(5, 4)"), // e.g., 0.9999 (99.99%) ColumnDefinition { name: "percentage".to_string(), field_type: "NUMERIC(5, 4)".to_string() }, // e.g., 0.9999 (99.99%)
("integer_val", "INTEGER"), ColumnDefinition { name: "integer_val".to_string(), field_type: "INTEGER".to_string() },
("result", "NUMERIC(30, 15)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(30, 15)".to_string() },
] ]
).await; ).await;
@@ -202,12 +198,12 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"financial_instruments", "financial_instruments",
vec![ vec![
("principal", "NUMERIC(16, 2)"), // Principal amount ColumnDefinition { name: "principal".to_string(), field_type: "NUMERIC(16, 2)".to_string() }, // Principal amount
("annual_rate", "NUMERIC(6, 5)"), // Interest rate (e.g., 0.05250) ColumnDefinition { name: "annual_rate".to_string(), field_type: "NUMERIC(6, 5)".to_string() }, // Interest rate (e.g., 0.05250)
("years", "INTEGER"), // Time period ColumnDefinition { name: "years".to_string(), field_type: "INTEGER".to_string() }, // Time period
("compounding_periods", "INTEGER"), // Compounding frequency ColumnDefinition { name: "compounding_periods".to_string(), field_type: "INTEGER".to_string() }, // Compounding frequency
("fees", "NUMERIC(10, 2)"), // Transaction fees ColumnDefinition { name: "fees".to_string(), field_type: "NUMERIC(10, 2)".to_string() }, // Transaction fees
("compound_interest", "NUMERIC(20, 8)"), // Result column ColumnDefinition { name: "compound_interest".to_string(), field_type: "NUMERIC(20, 8)".to_string() }, // Result column
] ]
).await; ).await;
@@ -237,9 +233,9 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"scientific_data", "scientific_data",
vec![ vec![
("large_number", "NUMERIC(30, 10)"), ColumnDefinition { name: "large_number".to_string(), field_type: "NUMERIC(30, 10)".to_string() },
("small_number", "NUMERIC(30, 20)"), ColumnDefinition { name: "small_number".to_string(), field_type: "NUMERIC(30, 20)".to_string() },
("result", "NUMERIC(35, 25)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(35, 25)".to_string() },
] ]
).await; ).await;
@@ -265,8 +261,8 @@ mod integration_tests {
let table_a_id = helper.create_table_with_types( let table_a_id = helper.create_table_with_types(
"table_a", "table_a",
vec![ vec![
("value_a", "NUMERIC(10, 2)"), ColumnDefinition { name: "value_a".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result_a", "NUMERIC(10, 2)"), ColumnDefinition { name: "result_a".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
] ]
).await; ).await;
println!("Created table_a with ID: {}", table_a_id); println!("Created table_a with ID: {}", table_a_id);
@@ -274,8 +270,8 @@ mod integration_tests {
let table_b_id = helper.create_table_with_types( let table_b_id = helper.create_table_with_types(
"table_b", "table_b",
vec![ vec![
("value_b", "NUMERIC(10, 2)"), ColumnDefinition { name: "value_b".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result_b", "NUMERIC(10, 2)"), ColumnDefinition { name: "result_b".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
] ]
).await; ).await;
println!("Created table_b with ID: {}", table_b_id); println!("Created table_b with ID: {}", table_b_id);
@@ -354,10 +350,10 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"error_test_table", "error_test_table",
vec![ vec![
("text_field", "TEXT"), ColumnDefinition { name: "text_field".to_string(), field_type: "TEXT".to_string() },
("numeric_field", "NUMERIC(10, 2)"), ColumnDefinition { name: "numeric_field".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("boolean_field", "BOOLEAN"), ColumnDefinition { name: "boolean_field".to_string(), field_type: "BOOLEAN".to_string() },
("bigint_field", "BIGINT"), ColumnDefinition { name: "bigint_field".to_string(), field_type: "BIGINT".to_string() },
] ]
).await; ).await;
@@ -417,11 +413,11 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"performance_table", "performance_table",
vec![ vec![
("x", "NUMERIC(15, 8)"), ColumnDefinition { name: "x".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("y", "NUMERIC(15, 8)"), ColumnDefinition { name: "y".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("z", "NUMERIC(15, 8)"), ColumnDefinition { name: "z".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("w", "NUMERIC(15, 8)"), ColumnDefinition { name: "w".to_string(), field_type: "NUMERIC(15, 8)".to_string() },
("complex_result", "NUMERIC(25, 12)"), ColumnDefinition { name: "complex_result".to_string(), field_type: "NUMERIC(25, 12)".to_string() },
] ]
).await; ).await;
@@ -456,11 +452,11 @@ mod integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"boundary_table", "boundary_table",
vec![ vec![
("min_numeric", "NUMERIC(1, 0)"), // Minimum: single digit, no decimal ColumnDefinition { name: "min_numeric".to_string(), field_type: "NUMERIC(1, 0)".to_string() }, // Minimum: single digit, no decimal
("max_numeric", "NUMERIC(1000, 999)"), // Maximum PostgreSQL allows ColumnDefinition { name: "max_numeric".to_string(), field_type: "NUMERIC(1000, 999)".to_string() }, // Maximum PostgreSQL allows
("zero_scale", "NUMERIC(10, 0)"), // Integer-like numeric ColumnDefinition { name: "zero_scale".to_string(), field_type: "NUMERIC(10, 0)".to_string() }, // Integer-like numeric
("max_scale", "NUMERIC(28, 28)"), // Maximum scale ColumnDefinition { name: "max_scale".to_string(), field_type: "NUMERIC(28, 28)".to_string() }, // Maximum scale
("result", "NUMERIC(1000, 999)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(1000, 999)".to_string() },
] ]
).await; ).await;
@@ -495,10 +491,10 @@ mod steel_decimal_integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"test_execution_table", "test_execution_table",
vec![ vec![
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("quantity", "INTEGER"), ColumnDefinition { name: "quantity".to_string(), field_type: "INTEGER".to_string() },
("tax_rate", "NUMERIC(5, 4)"), ColumnDefinition { name: "tax_rate".to_string(), field_type: "NUMERIC(5, 4)".to_string() },
("result", "NUMERIC(15, 4)"), // Add a result column ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(15, 4)".to_string() }, // Add a result column
] ]
).await; ).await;
println!("Created test table with ID: {}", table_id); println!("Created test table with ID: {}", table_id);
@@ -575,9 +571,9 @@ mod steel_decimal_integration_tests {
let table_id = helper.create_table_with_types( let table_id = helper.create_table_with_types(
"precision_test_table", "precision_test_table",
vec![ vec![
("precise_value", "NUMERIC(20, 12)"), ColumnDefinition { name: "precise_value".to_string(), field_type: "NUMERIC(20, 12)".to_string() },
("multiplier", "NUMERIC(20, 12)"), ColumnDefinition { name: "multiplier".to_string(), field_type: "NUMERIC(20, 12)".to_string() },
("result", "NUMERIC(25, 15)"), // Add result column ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(25, 15)".to_string() }, // Add result column
] ]
).await; ).await;
println!("Created precision test table with ID: {}", table_id); println!("Created precision test table with ID: {}", table_id);

View File

@@ -3,6 +3,7 @@
use crate::common::setup_isolated_db; use crate::common::setup_isolated_db;
use server::table_script::handlers::post_table_script::post_table_script; use server::table_script::handlers::post_table_script::post_table_script;
use common::proto::komp_ac::table_script::PostTableScriptRequest; use common::proto::komp_ac::table_script::PostTableScriptRequest;
use common::proto::komp_ac::table_definition::ColumnDefinition;
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
@@ -11,15 +12,10 @@ async fn create_test_table(
pool: &PgPool, pool: &PgPool,
schema_id: i64, schema_id: i64,
table_name: &str, table_name: &str,
columns: Vec<(&str, &str)>, columns: Vec<ColumnDefinition>,
) -> i64 { ) -> i64 {
let column_definitions: Vec<String> = columns let columns_json = serde_json::to_value(columns).unwrap();
.iter() let indexes_json = serde_json::json!([]);
.map(|(name, type_def)| format!("\"{}\" {}", name, type_def))
.collect();
let columns_json = json!(column_definitions);
let indexes_json = json!([]);
sqlx::query_scalar!( sqlx::query_scalar!(
r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes) r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes)
@@ -67,7 +63,10 @@ async fn test_reject_bigint_target_column() {
&pool, &pool,
schema_id, schema_id,
"bigint_table", "bigint_table",
vec![("name", "TEXT"), ("big_number", "BIGINT")] vec![
ColumnDefinition { name: "name".to_string(), field_type: "TEXT".to_string() },
ColumnDefinition { name: "big_number".to_string(), field_type: "BIGINT".to_string() }
]
).await; ).await;
let request = PostTableScriptRequest { let request = PostTableScriptRequest {
@@ -99,7 +98,10 @@ async fn test_reject_date_target_column() {
&pool, &pool,
schema_id, schema_id,
"date_table", "date_table",
vec![("name", "TEXT"), ("event_date", "DATE")] vec![
ColumnDefinition { name: "name".to_string(), field_type: "TEXT".to_string() },
ColumnDefinition { name: "event_date".to_string(), field_type: "DATE".to_string() }
]
).await; ).await;
let request = PostTableScriptRequest { let request = PostTableScriptRequest {
@@ -131,7 +133,10 @@ async fn test_reject_timestamptz_target_column() {
&pool, &pool,
schema_id, schema_id,
"timestamp_table", "timestamp_table",
vec![("name", "TEXT"), ("created_time", "TIMESTAMPTZ")] vec![
ColumnDefinition { name: "name".to_string(), field_type: "TEXT".to_string() },
ColumnDefinition { name: "created_time".to_string(), field_type: "TIMESTAMPTZ".to_string() }
]
).await; ).await;
let request = PostTableScriptRequest { let request = PostTableScriptRequest {
@@ -164,9 +169,9 @@ async fn test_reject_text_in_mathematical_operations() {
schema_id, schema_id,
"text_math_table", "text_math_table",
vec![ vec![
("description", "TEXT"), ColumnDefinition { name: "description".to_string(), field_type: "TEXT".to_string() },
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result", "NUMERIC(10, 2)") ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(10, 2)".to_string() }
] ]
).await; ).await;
@@ -202,9 +207,9 @@ async fn test_reject_boolean_in_mathematical_operations() {
schema_id, schema_id,
"boolean_math_table", "boolean_math_table",
vec![ vec![
("is_active", "BOOLEAN"), ColumnDefinition { name: "is_active".to_string(), field_type: "BOOLEAN".to_string() },
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result", "NUMERIC(10, 2)") ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(10, 2)".to_string() }
] ]
).await; ).await;
@@ -240,8 +245,8 @@ async fn test_reject_bigint_in_mathematical_operations() {
schema_id, schema_id,
"bigint_math_table", "bigint_math_table",
vec![ vec![
("big_value", "BIGINT"), ColumnDefinition { name: "big_value".to_string(), field_type: "BIGINT".to_string() },
("result", "NUMERIC(10, 2)") ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(10, 2)".to_string() }
] ]
).await; ).await;
@@ -277,10 +282,10 @@ async fn test_allow_valid_script_with_allowed_types() {
schema_id, schema_id,
"allowed_types_table", "allowed_types_table",
vec![ vec![
("name", "TEXT"), ColumnDefinition { name: "name".to_string(), field_type: "TEXT".to_string() },
("count", "INTEGER"), ColumnDefinition { name: "count".to_string(), field_type: "INTEGER".to_string() },
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("computed_value", "TEXT") ColumnDefinition { name: "computed_value".to_string(), field_type: "TEXT".to_string() }
] ]
).await; ).await;
@@ -312,9 +317,9 @@ async fn test_allow_integer_and_numeric_in_math_operations() {
schema_id, schema_id,
"math_allowed_table", "math_allowed_table",
vec![ vec![
("quantity", "INTEGER"), ColumnDefinition { name: "quantity".to_string(), field_type: "INTEGER".to_string() },
("price", "NUMERIC(10, 2)"), ColumnDefinition { name: "price".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("total", "NUMERIC(12, 2)") ColumnDefinition { name: "total".to_string(), field_type: "NUMERIC(12, 2)".to_string() }
] ]
).await; ).await;
@@ -363,14 +368,19 @@ async fn test_script_without_table_links_should_fail() {
&pool, &pool,
schema_id, schema_id,
"table_a", "table_a",
vec![("value_a", "INTEGER"), ("result", "INTEGER")] vec![
ColumnDefinition { name: "value_a".to_string(), field_type: "INTEGER".to_string() },
ColumnDefinition { name: "result".to_string(), field_type: "INTEGER".to_string() }
]
).await; ).await;
let _table_b_id = create_test_table( let _table_b_id = create_test_table(
&pool, &pool,
schema_id, schema_id,
"table_b", "table_b",
vec![("value_b", "INTEGER")] vec![
ColumnDefinition { name: "value_b".to_string(), field_type: "INTEGER".to_string() }
]
).await; ).await;
// DON'T create a link between the tables // DON'T create a link between the tables
@@ -404,14 +414,19 @@ async fn test_script_with_table_links_should_succeed() {
&pool, &pool,
schema_id, schema_id,
"linked_table_a", "linked_table_a",
vec![("value_a", "INTEGER"), ("result", "INTEGER")] vec![
ColumnDefinition { name: "value_a".to_string(), field_type: "INTEGER".to_string() },
ColumnDefinition { name: "result".to_string(), field_type: "INTEGER".to_string() }
]
).await; ).await;
let table_b_id = create_test_table( let table_b_id = create_test_table(
&pool, &pool,
schema_id, schema_id,
"linked_table_b", "linked_table_b",
vec![("value_b", "INTEGER")] vec![
ColumnDefinition { name: "value_b".to_string(), field_type: "INTEGER".to_string() }
]
).await; ).await;
// Create a link between the tables (table_a can access table_b) // Create a link between the tables (table_a can access table_b)

View File

@@ -3,6 +3,7 @@
use crate::common::setup_isolated_db; use crate::common::setup_isolated_db;
use server::table_script::handlers::post_table_script::post_table_script; use server::table_script::handlers::post_table_script::post_table_script;
use common::proto::komp_ac::table_script::PostTableScriptRequest; use common::proto::komp_ac::table_script::PostTableScriptRequest;
use common::proto::komp_ac::table_definition::ColumnDefinition;
use rstest::*; use rstest::*;
use serde_json::json; use serde_json::json;
use sqlx::PgPool; use sqlx::PgPool;
@@ -76,15 +77,10 @@ async fn create_test_table(
pool: &PgPool, pool: &PgPool,
schema_id: i64, schema_id: i64,
table_name: &str, table_name: &str,
columns: Vec<(&str, &str)>, columns: Vec<ColumnDefinition>,
) -> i64 { ) -> i64 {
let column_definitions: Vec<String> = columns let columns_json = serde_json::to_value(columns).unwrap();
.iter() let indexes_json = serde_json::json!([]);
.map(|(name, type_def)| format!("\"{}\" {}", name, type_def))
.collect();
let columns_json = json!(column_definitions);
let indexes_json = json!([]);
sqlx::query_scalar!( sqlx::query_scalar!(
r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes) r#"INSERT INTO table_definitions (schema_id, table_name, columns, indexes)
@@ -123,8 +119,17 @@ async fn test_allowed_types_in_math_operations(
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create table with all allowed mathematical types plus a result column // Create table with all allowed mathematical types plus a result column
let mut columns = allowed_math_types.clone(); let mut columns: Vec<ColumnDefinition> = allowed_math_types
columns.push(("result", "NUMERIC(30, 15)")); .iter()
.map(|(name, field_type)| ColumnDefinition {
name: name.to_string(),
field_type: field_type.to_string(),
})
.collect();
columns.push(ColumnDefinition {
name: "result".to_string(),
field_type: "NUMERIC(30, 15)".to_string(),
});
let table_id = create_test_table(&pool, schema_id, "math_test_table", columns).await; let table_id = create_test_table(&pool, schema_id, "math_test_table", columns).await;
@@ -172,8 +177,17 @@ async fn test_prohibited_types_in_math_operations(
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create table with prohibited types plus a valid result column // Create table with prohibited types plus a valid result column
let mut columns = prohibited_math_types.clone(); let mut columns: Vec<ColumnDefinition> = prohibited_math_types
columns.push(("result", "NUMERIC(15, 6)")); .iter()
.map(|(name, field_type)| ColumnDefinition {
name: name.to_string(),
field_type: field_type.to_string(),
})
.collect();
columns.push(ColumnDefinition {
name: "result".to_string(),
field_type: "NUMERIC(15, 6)".to_string(),
});
let table_id = create_test_table(&pool, schema_id, "prohibited_math_table", columns).await; let table_id = create_test_table(&pool, schema_id, "prohibited_math_table", columns).await;
@@ -225,8 +239,17 @@ async fn test_prohibited_target_column_types(
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create table with prohibited target types plus some valid source columns // Create table with prohibited target types plus some valid source columns
let mut columns = prohibited_target_types.clone(); let mut columns: Vec<ColumnDefinition> = prohibited_target_types
columns.push(("amount", "NUMERIC(10, 2)")); .iter()
.map(|(name, field_type)| ColumnDefinition {
name: name.to_string(),
field_type: field_type.to_string(),
})
.collect();
columns.push(ColumnDefinition {
name: "amount".to_string(),
field_type: "NUMERIC(10, 2)".to_string(),
});
let table_id = create_test_table(&pool, schema_id, "prohibited_target_table", columns).await; let table_id = create_test_table(&pool, schema_id, "prohibited_target_table", columns).await;
@@ -261,7 +284,12 @@ async fn test_system_column_restrictions(#[case] target_column: &str, #[case] de
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![("amount", "NUMERIC(10, 2)")]; let columns: Vec<ColumnDefinition> = vec![
ColumnDefinition {
name: "amount".to_string(),
field_type: "NUMERIC(10, 2)".to_string(),
}
];
let table_id = create_test_table(&pool, schema_id, "system_test_table", columns).await; let table_id = create_test_table(&pool, schema_id, "system_test_table", columns).await;
let script = r#"(+ "10" "20")"#; let script = r#"(+ "10" "20")"#;
@@ -290,22 +318,22 @@ async fn test_comprehensive_type_matrix() {
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
// Create comprehensive table with all type categories // Create comprehensive table with all type categories
let all_columns = vec![ let all_columns: Vec<ColumnDefinition> = vec![
// Allowed math types // Allowed math types
("integer_col", "INTEGER"), ColumnDefinition { name: "integer_col".to_string(), field_type: "INTEGER".to_string() },
("numeric_col", "NUMERIC(10, 2)"), ColumnDefinition { name: "numeric_col".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("high_precision", "NUMERIC(28, 15)"), ColumnDefinition { name: "high_precision".to_string(), field_type: "NUMERIC(28, 15)".to_string() },
// Prohibited math types // Prohibited math types
("text_col", "TEXT"), ColumnDefinition { name: "text_col".to_string(), field_type: "TEXT".to_string() },
("boolean_col", "BOOLEAN"), ColumnDefinition { name: "boolean_col".to_string(), field_type: "BOOLEAN".to_string() },
("bigint_col", "BIGINT"), ColumnDefinition { name: "bigint_col".to_string(), field_type: "BIGINT".to_string() },
("date_col", "DATE"), ColumnDefinition { name: "date_col".to_string(), field_type: "DATE".to_string() },
("timestamp_col", "TIMESTAMPTZ"), ColumnDefinition { name: "timestamp_col".to_string(), field_type: "TIMESTAMPTZ".to_string() },
// Result columns // Result columns
("result_numeric", "NUMERIC(20, 8)"), ColumnDefinition { name: "result_numeric".to_string(), field_type: "NUMERIC(20, 8)".to_string() },
("result_text", "TEXT"), ColumnDefinition { name: "result_text".to_string(), field_type: "TEXT".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "comprehensive_table", all_columns).await; let table_id = create_test_table(&pool, schema_id, "comprehensive_table", all_columns).await;
@@ -361,11 +389,11 @@ async fn test_complex_mathematical_expressions() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("principal", "NUMERIC(16, 2)"), ColumnDefinition { name: "principal".to_string(), field_type: "NUMERIC(16, 2)".to_string() },
("rate", "NUMERIC(6, 5)"), ColumnDefinition { name: "rate".to_string(), field_type: "NUMERIC(6, 5)".to_string() },
("years", "INTEGER"), ColumnDefinition { name: "years".to_string(), field_type: "INTEGER".to_string() },
("compound_result", "NUMERIC(20, 8)"), ColumnDefinition { name: "compound_result".to_string(), field_type: "NUMERIC(20, 8)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "financial_table", columns).await; let table_id = create_test_table(&pool, schema_id, "financial_table", columns).await;
@@ -395,9 +423,9 @@ async fn test_nonexistent_column_reference() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result", "NUMERIC(10, 2)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "simple_table", columns).await; let table_id = create_test_table(&pool, schema_id, "simple_table", columns).await;
@@ -427,9 +455,9 @@ async fn test_nonexistent_table_reference() {
let pool = setup_isolated_db().await; let pool = setup_isolated_db().await;
let schema_id = get_default_schema_id(&pool).await; let schema_id = get_default_schema_id(&pool).await;
let columns = vec![ let columns: Vec<ColumnDefinition> = vec![
("amount", "NUMERIC(10, 2)"), ColumnDefinition { name: "amount".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
("result", "NUMERIC(10, 2)"), ColumnDefinition { name: "result".to_string(), field_type: "NUMERIC(10, 2)".to_string() },
]; ];
let table_id = create_test_table(&pool, schema_id, "existing_table", columns).await; let table_id = create_test_table(&pool, schema_id, "existing_table", columns).await;

View File

@@ -91,7 +91,7 @@ async fn create_initial_record(
// Set different initial values based on the test case to satisfy validation scripts // Set different initial values based on the test case to satisfy validation scripts
match (profile_name, table_name) { match (profile_name, table_name) {
("test_put_complex", "order") => { ("test_put_complex", "order") => {
// For complex formula: (+ (* @price @quantity) (* (* @price @quantity) 0.08)) // For complex formula: (+ (* $price $quantity) (* (* $price $quantity) 0.08))
// With price=10.00, quantity=1: (10*1) + (10*1*0.08) = 10 + 0.8 = 10.8 // With price=10.00, quantity=1: (10*1) + (10*1*0.08) = 10 + 0.8 = 10.8
data.insert("price".to_string(), ProtoValue { kind: Some(Kind::StringValue("10.00".to_string())) }); data.insert("price".to_string(), ProtoValue { kind: Some(Kind::StringValue("10.00".to_string())) });
data.insert("quantity".to_string(), ProtoValue { kind: Some(Kind::NumberValue(1.0)) }); data.insert("quantity".to_string(), ProtoValue { kind: Some(Kind::NumberValue(1.0)) });
@@ -99,7 +99,7 @@ async fn create_initial_record(
data.insert("percentage".to_string(), ProtoValue { kind: Some(Kind::StringValue("100.00".to_string())) }); data.insert("percentage".to_string(), ProtoValue { kind: Some(Kind::StringValue("100.00".to_string())) });
}, },
("test_put_division", "calculation") => { ("test_put_division", "calculation") => {
// For division: (/ @total @price) // For division: (/ $total $price)
// With total=10.00, price=10.00: 10/10 = 1 // With total=10.00, price=10.00: 10/10 = 1
data.insert("price".to_string(), ProtoValue { kind: Some(Kind::StringValue("10.00".to_string())) }); data.insert("price".to_string(), ProtoValue { kind: Some(Kind::StringValue("10.00".to_string())) });
data.insert("quantity".to_string(), ProtoValue { kind: Some(Kind::NumberValue(1.0)) }); data.insert("quantity".to_string(), ProtoValue { kind: Some(Kind::NumberValue(1.0)) });
@@ -142,7 +142,7 @@ async fn test_put_basic_arithmetic_validation_success(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "total".to_string(), target_column: "total".to_string(),
script: "(* @price @quantity)".to_string(), script: "(* $price $quantity)".to_string(),
description: "Total = Price × Quantity".to_string(), description: "Total = Price × Quantity".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -180,7 +180,7 @@ async fn test_put_basic_arithmetic_validation_failure(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "total".to_string(), target_column: "total".to_string(),
script: "(* @price @quantity)".to_string(), script: "(* $price $quantity)".to_string(),
description: "Total = Price × Quantity".to_string(), description: "Total = Price × Quantity".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -224,7 +224,7 @@ async fn test_put_complex_formula_validation(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "total".to_string(), target_column: "total".to_string(),
script: "(+ (* @price @quantity) (* (* @price @quantity) 0.08))".to_string(), script: "(+ (* $price $quantity) (* (* $price $quantity) 0.08))".to_string(),
description: "Total with 8% tax".to_string(), description: "Total with 8% tax".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -261,7 +261,7 @@ async fn test_put_division_with_precision(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "percentage".to_string(), target_column: "percentage".to_string(),
script: "(/ @total @price)".to_string(), script: "(/ $total $price)".to_string(),
description: "Percentage = Total / Price".to_string(), description: "Percentage = Total / Price".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -326,7 +326,7 @@ async fn test_put_advanced_math_functions(pool: PgPool) {
let sqrt_script = PostTableScriptRequest { let sqrt_script = PostTableScriptRequest {
table_definition_id: table_row.id, table_definition_id: table_row.id,
target_column: "square_root".to_string(), target_column: "square_root".to_string(),
script: "(sqrt @input)".to_string(), script: "(sqrt $input)".to_string(),
description: "Square root validation".to_string(), description: "Square root validation".to_string(),
}; };
post_table_script(&pool, sqrt_script).await.unwrap(); post_table_script(&pool, sqrt_script).await.unwrap();
@@ -334,7 +334,7 @@ async fn test_put_advanced_math_functions(pool: PgPool) {
let power_script = PostTableScriptRequest { let power_script = PostTableScriptRequest {
table_definition_id: table_row.id, table_definition_id: table_row.id,
target_column: "power_result".to_string(), target_column: "power_result".to_string(),
script: "(^ @input 2.0)".to_string(), script: "(^ $input 2.0)".to_string(),
description: "Power function validation".to_string(), description: "Power function validation".to_string(),
}; };
post_table_script(&pool, power_script).await.unwrap(); post_table_script(&pool, power_script).await.unwrap();
@@ -389,7 +389,7 @@ async fn test_put_financial_calculations(pool: PgPool) {
let compound_script = PostTableScriptRequest { let compound_script = PostTableScriptRequest {
table_definition_id: table_row.id, table_definition_id: table_row.id,
target_column: "compound_result".to_string(), target_column: "compound_result".to_string(),
script: "(* @principal (^ (+ 1.0 @rate) @time))".to_string(), script: "(* $principal (^ (+ 1.0 $rate) $time))".to_string(),
description: "Compound interest calculation".to_string(), description: "Compound interest calculation".to_string(),
}; };
post_table_script(&pool, compound_script).await.unwrap(); post_table_script(&pool, compound_script).await.unwrap();
@@ -397,7 +397,7 @@ async fn test_put_financial_calculations(pool: PgPool) {
let percentage_script = PostTableScriptRequest { let percentage_script = PostTableScriptRequest {
table_definition_id: table_row.id, table_definition_id: table_row.id,
target_column: "percentage_result".to_string(), target_column: "percentage_result".to_string(),
script: "(* @principal @rate)".to_string(), script: "(* $principal $rate)".to_string(),
description: "Percentage calculation".to_string(), description: "Percentage calculation".to_string(),
}; };
post_table_script(&pool, percentage_script).await.unwrap(); post_table_script(&pool, percentage_script).await.unwrap();
@@ -441,7 +441,7 @@ async fn test_put_partial_update_with_validation(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "total".to_string(), target_column: "total".to_string(),
script: "(* @price @quantity)".to_string(), script: "(* $price $quantity)".to_string(),
description: "Total = Price × Quantity".to_string(), description: "Total = Price × Quantity".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -553,7 +553,7 @@ async fn test_put_steel_script_error_handling(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_def_id, table_definition_id: table_def_id,
target_column: "total".to_string(), target_column: "total".to_string(),
script: "(/ @price 0.0)".to_string(), script: "(/ $price 0.0)".to_string(),
description: "Error test".to_string(), description: "Error test".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -623,7 +623,7 @@ async fn test_decimal_precision_behavior(pool: PgPool) {
let script_request = PostTableScriptRequest { let script_request = PostTableScriptRequest {
table_definition_id: table_row.id, table_definition_id: table_row.id,
target_column: "result".to_string(), target_column: "result".to_string(),
script: "(/ @dividend @divisor)".to_string(), script: "(/ $dividend $divisor)".to_string(),
description: "Division test for precision".to_string(), description: "Division test for precision".to_string(),
}; };
post_table_script(&pool, script_request).await.unwrap(); post_table_script(&pool, script_request).await.unwrap();
@@ -816,7 +816,7 @@ async fn test_put_complex_formula_validation_via_handlers(pool: PgPool) {
"test_put_complex_handlers", "test_put_complex_handlers",
"order", "order",
"total", "total",
"(+ (* @price @quantity) (* (* @price @quantity) 0.08))", // Total with 8% tax "(+ (* $price $quantity) (* (* $price $quantity) 0.08))", // Total with 8% tax
) )
.await .await
.expect("Failed to add validation script"); .expect("Failed to add validation script");
@@ -891,7 +891,7 @@ async fn test_put_basic_arithmetic_validation_via_handlers(pool: PgPool) {
"test_put_arithmetic_handlers", "test_put_arithmetic_handlers",
"invoice", "invoice",
"total", "total",
"(* @price @quantity)", // Simple: Total = Price × Quantity "(* $price $quantity)", // Simple: Total = Price × Quantity
) )
.await .await
.expect("Failed to add validation script"); .expect("Failed to add validation script");
@@ -955,7 +955,7 @@ async fn test_put_arithmetic_validation_failure_via_handlers(pool: PgPool) {
"test_put_arithmetic_fail_handlers", "test_put_arithmetic_fail_handlers",
"invoice", "invoice",
"total", "total",
"(* @price @quantity)", "(* $price $quantity)",
) )
.await .await
.expect("Failed to add validation script"); .expect("Failed to add validation script");