diff --git a/server/src/tables_data/handlers/post_table_data.rs b/server/src/tables_data/handlers/post_table_data.rs index 9665da5..299829d 100644 --- a/server/src/tables_data/handlers/post_table_data.rs +++ b/server/src/tables_data/handlers/post_table_data.rs @@ -73,37 +73,33 @@ pub async fn post_table_data( columns.push((name, sql_type)); } - // Get required relationships - let required_links = sqlx::query!( + // Get all foreign key columns for this table + let fk_columns = sqlx::query!( r#"SELECT ltd.table_name FROM table_definition_links tdl JOIN table_definitions ltd ON tdl.linked_table_id = ltd.id - WHERE tdl.source_table_id = $1 AND tdl.is_required = true"#, + WHERE tdl.source_table_id = $1"#, table_def.id ) .fetch_all(db_pool) .await - .map_err(|e| Status::internal(format!("Link lookup error: {}", e)))?; + .map_err(|e| Status::internal(format!("Foreign key lookup error: {}", e)))?; - // Build required columns list - let mut required_columns = vec![]; - for link in required_links { - let base_name = link.table_name.split('_').last().unwrap_or(&link.table_name); - required_columns.push(format!("{}_id", base_name)); + // Build system columns with foreign keys + let mut system_columns = vec!["deleted".to_string()]; + for fk in fk_columns { + let base_name = fk.table_name.split('_').last().unwrap_or(&fk.table_name); + system_columns.push(format!("{}_id", base_name)); } - // Validate required columns - for col in &required_columns { - if !data.contains_key(col) { - return Err(Status::invalid_argument(format!("Missing required column: {}", col))); - } - } + // Convert to HashSet for faster lookups + let system_columns_set: std::collections::HashSet<_> = system_columns.iter().map(|s| s.as_str()).collect(); // Validate all data columns - let system_columns = ["deleted"]; let user_columns: Vec<&String> = columns.iter().map(|(name, _)| name).collect(); for key in data.keys() { - if !system_columns.contains(&key.as_str()) && !user_columns.contains(&key) { + if !system_columns_set.contains(key.as_str()) && + !user_columns.contains(&&key.to_string()) { return Err(Status::invalid_argument(format!("Invalid column: {}", key))); } } @@ -169,9 +165,10 @@ pub async fn post_table_data( let mut param_idx = 1; for (col, value) in data { - let sql_type = if system_columns.contains(&col.as_str()) { + let sql_type = if system_columns_set.contains(col.as_str()) { match col.as_str() { "deleted" => "BOOLEAN", + _ if col.ends_with("_id") => "BIGINT", // Handle foreign keys _ => return Err(Status::invalid_argument("Invalid system column")), } } else { @@ -206,6 +203,12 @@ pub async fn post_table_data( params.add(dt.with_timezone(&Utc)) .map_err(|e| Status::invalid_argument(format!("Failed to add timestamp parameter for {}: {}", col, e)))?; }, + "BIGINT" => { + let val = value.parse::() + .map_err(|_| Status::invalid_argument(format!("Invalid integer for {}", col)))?; + params.add(val) + .map_err(|e| Status::invalid_argument(format!("Failed to add integer parameter for {}: {}", col, e)))?; + }, _ => return Err(Status::invalid_argument(format!("Unsupported type {}", sql_type))), }