// server/src/table_definition/handlers/delete_table.rs use tonic::Status; use sqlx::PgPool; use common::proto::multieko2::table_definition::{DeleteTableRequest, DeleteTableResponse}; pub async fn delete_table( db_pool: &PgPool, request: DeleteTableRequest, ) -> Result { let mut transaction = db_pool.begin().await .map_err(|e| Status::internal(format!("Failed to start transaction: {}", e)))?; // Step 1: Get profile and validate existence let profile = sqlx::query!( "SELECT id FROM profiles WHERE name = $1", request.profile_name ) .fetch_optional(&mut *transaction) .await .map_err(|e| Status::internal(format!("Profile lookup failed: {}", e)))?; let profile_id = match profile { Some(p) => p.id, None => return Err(Status::not_found("Profile not found")), }; // Step 2: Get table definition and validate existence let table_def = sqlx::query!( "SELECT id FROM table_definitions WHERE profile_id = $1 AND table_name = $2", profile_id, request.table_name ) .fetch_optional(&mut *transaction) .await .map_err(|e| Status::internal(format!("Table lookup failed: {}", e)))?; let table_def_id = match table_def { Some(t) => t.id, None => return Err(Status::not_found("Table not found in profile")), }; // Step 3: Drop the actual PostgreSQL table with CASCADE sqlx::query(&format!(r#"DROP TABLE IF EXISTS "{}" CASCADE"#, request.table_name)) .execute(&mut *transaction) .await .map_err(|e| Status::internal(format!("Table drop failed: {}", e)))?; // Step 4: Delete from table_definitions sqlx::query!( "DELETE FROM table_definitions WHERE id = $1", table_def_id ) .execute(&mut *transaction) .await .map_err(|e| Status::internal(format!("Definition deletion failed: {}", e)))?; // Step 5: Check and clean up profile if empty let remaining = sqlx::query!( "SELECT COUNT(*) as count FROM table_definitions WHERE profile_id = $1", profile_id ) .fetch_one(&mut *transaction) .await .map_err(|e| Status::internal(format!("Count query failed: {}", e)))?; if remaining.count.unwrap_or(1) == 0 { sqlx::query!( "DELETE FROM profiles WHERE id = $1", profile_id ) .execute(&mut *transaction) .await .map_err(|e| Status::internal(format!("Profile cleanup failed: {}", e)))?; } transaction.commit().await .map_err(|e| Status::internal(format!("Transaction commit failed: {}", e)))?; Ok(DeleteTableResponse { success: true, message: format!("Table '{}' and its definition were successfully removed", request.table_name), }) }