From bca2cf925d145cad5ce76b69f89d0865022a2f71 Mon Sep 17 00:00:00 2001 From: filipriec Date: Mon, 3 Mar 2025 12:03:41 +0100 Subject: [PATCH] table creation columns is now not accessed via raw sql --- common/proto/table_definition.proto | 2 +- common/src/proto/descriptor.bin | Bin 12962 -> 12964 bytes .../src/proto/multieko2.table_definition.rs | 2 +- .../table_definition/docs/push_new_table.txt | 78 ++++++++++++++++++ .../handlers/post_table_definition.rs | 33 +++++--- 5 files changed, 101 insertions(+), 14 deletions(-) create mode 100644 server/src/table_definition/docs/push_new_table.txt diff --git a/common/proto/table_definition.proto b/common/proto/table_definition.proto index a005be1..9d3fc8c 100644 --- a/common/proto/table_definition.proto +++ b/common/proto/table_definition.proto @@ -19,7 +19,7 @@ message PostTableDefinitionRequest { message ColumnDefinition { string name = 1; - string data_type = 2; + string field_type = 2; } message TableDefinitionResponse { diff --git a/common/src/proto/descriptor.bin b/common/src/proto/descriptor.bin index 8ce08e929edf8c0e8974f7c0a61bda994b611c0a..ba8766b98bc4c479f006bab5f66b43c024949589 100644 GIT binary patch delta 79 zcmZ3Kx+HbOX-&rKo6l(aF*3SNmey96lI7w`%S_Eli7%-vNR?nxVAS9Y;slFqj?%uz g!YDP_(m \dt + List of relations + Schema | Name | Type | Owner +--------+--------------------------------+-------+---------------- + public | 2025_company_data | table | multi_psql_dev + public | 2025_multi_dependent_table3 | table | multi_psql_dev + public | 2025_multi_dependent_table4 | table | multi_psql_dev + public | 2025_multi_dependent_table5 | table | multi_psql_dev + public | _sqlx_migrations | table | multi_psql_dev + public | adresar | table | multi_psql_dev + public | profiles | table | multi_psql_dev + public | table_definitions | table | multi_psql_dev + public | uctovnictvo | table | multi_psql_dev + public | ud_2025_linked_test_table | table | multi_psql_dev + public | ud_2025_linked_test_table2 | table | multi_psql_dev + public | ud_2025_linked_test_table3 | table | multi_psql_dev + public | ud_2025_multi_dependent_table | table | multi_psql_dev + public | ud_2025_multi_dependent_table2 | table | multi_psql_dev + public | ud_2025_profile_table | table | multi_psql_dev + public | ud_2025_test_table | table | multi_psql_dev + public | ud_2025_test_table_no_linked | table | multi_psql_dev +(17 rows) + +multi_rust_dev=> \d 2025_company_data + Table "public.2025_company_data" + Column | Type | Collation | Nullable | Default +-----------------------+--------------------------+-----------+----------+------------------------------------------------- + id | bigint | | not null | nextval('"2025_company_data_id_seq"'::regclass) + deleted | boolean | | not null | false + firma | text | | not null | + 2025_test_table_id | bigint | | not null | + 2025_company_name | text | | | + 2025_textfield | text | | | + 2025_textfield2 | text | | | + 2025_textfield3 | text | | | + 2025_headquarters_psc | text | | | + 2025_contact_phone | character varying(15) | | | + 2025_office_address | text | | | + 2025_support_email | character varying(255) | | | + 2025_is_active | boolean | | | + 2025_last_updated | timestamp with time zone | | | + created_at | timestamp with time zone | | | CURRENT_TIMESTAMP +Indexes: + "2025_company_data_pkey" PRIMARY KEY, btree (id) + "idx_2025_company_data_2025_company_name" btree ("2025_company_name") + "idx_2025_company_data_2025_is_active" btree ("2025_is_active") + "idx_2025_company_data_2025_test_table_id" btree ("2025_test_table_id") + "idx_2025_company_data_firma" btree (firma) +Foreign-key constraints: + "2025_company_data_2025_test_table_id_fkey" FOREIGN KEY ("2025_test_table_id") REFERENCES ud_2025_test_table(id) + +multi_rust_dev=> diff --git a/server/src/table_definition/handlers/post_table_definition.rs b/server/src/table_definition/handlers/post_table_definition.rs index a3cbbac..929bc5b 100644 --- a/server/src/table_definition/handlers/post_table_definition.rs +++ b/server/src/table_definition/handlers/post_table_definition.rs @@ -5,11 +5,15 @@ use serde_json::json; use time::OffsetDateTime; use common::proto::multieko2::table_definition::{PostTableDefinitionRequest, TableDefinitionResponse}; -const VALID_DATA_TYPES: &[&str] = &["TEXT", "INTEGER", "BIGINT", "BOOLEAN", "TIMESTAMPTZ", "NUMERIC"]; - -fn is_valid_data_type(dt: &str) -> bool { - VALID_DATA_TYPES.contains(&dt.to_uppercase().as_str()) -} +const PREDEFINED_FIELD_TYPES: &[(&str, &str)] = &[ + ("text", "TEXT"), + ("psc", "TEXT"), + ("phone", "VARCHAR(15)"), + ("address", "TEXT"), + ("email", "VARCHAR(255)"), + ("boolean", "BOOLEAN"), + ("timestamp", "TIMESTAMPTZ"), +]; fn is_valid_identifier(s: &str) -> bool { !s.is_empty() && @@ -28,6 +32,14 @@ fn sanitize_identifier(s: &str) -> String { format!("{}_{}", year, cleaned) } +fn map_field_type(field_type: &str) -> Result<&str, Status> { + PREDEFINED_FIELD_TYPES + .iter() + .find(|(key, _)| *key == field_type.to_lowercase().as_str()) + .map(|(_, sql_type)| *sql_type) + .ok_or_else(|| Status::invalid_argument(format!("Invalid field type: {}", field_type))) +} + pub async fn post_table_definition( db_pool: &PgPool, mut request: PostTableDefinitionRequest, @@ -52,7 +64,6 @@ pub async fn post_table_definition( // Validate linked table if provided let linked_table_id; if let Some(lt_name) = &request.linked_table_name { - // Lookup the table with the EXACT provided name let lt_record = sqlx::query!( "SELECT id FROM table_definitions WHERE profile_id = $1 AND table_name = $2", @@ -78,10 +89,9 @@ pub async fn post_table_definition( if !is_valid_identifier(&col_def.name) { return Err(Status::invalid_argument("Invalid column name")); } - if !is_valid_data_type(&col_def.data_type) { - return Err(Status::invalid_argument("Invalid data type")); - } - columns.push(format!("\"{}\" {}", col_name, col_def.data_type)); + + let sql_type = map_field_type(&col_def.field_type)?; + columns.push(format!("\"{}\" {}", col_name, sql_type)); } let mut indexes = Vec::new(); @@ -155,9 +165,8 @@ fn generate_table_sql( ]; if let Some(linked) = linked_table { - // Extract base name without prefix for relationship let parts: Vec<&str> = linked.splitn(2, '_').collect(); - let base_name = parts.get(1).unwrap_or(&linked); // "profile_table" + let base_name = parts.get(1).unwrap_or(&linked); system_columns.push( format!("\"{}_id\" BIGINT NOT NULL REFERENCES \"{}\"(id)",