// 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 schema and validate existence let schema = sqlx::query!( "SELECT id, name FROM schemas WHERE name = $1", request.profile_name ) .fetch_optional(&mut *transaction) .await .map_err(|e| Status::internal(format!("Schema lookup failed: {}", e)))?; let (schema_id, schema_name) = match schema { Some(s) => (s.id, s.name), 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 schema_id = $1 AND table_name = $2", schema_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 (schema-qualified) let drop_table_sql = format!(r#"DROP TABLE IF EXISTS "{}"."{}" CASCADE"#, schema_name, request.table_name); sqlx::query(&drop_table_sql) .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 schema if empty let remaining = sqlx::query!( "SELECT COUNT(*) as count FROM table_definitions WHERE schema_id = $1", schema_id ) .fetch_one(&mut *transaction) .await .map_err(|e| Status::internal(format!("Count query failed: {}", e)))?; if remaining.count.unwrap_or(1) == 0 { // Drop the PostgreSQL schema if empty let drop_schema_sql = format!(r#"DROP SCHEMA IF EXISTS "{}" CASCADE"#, schema_name); sqlx::query(&drop_schema_sql) .execute(&mut *transaction) .await .map_err(|e| Status::internal(format!("Schema drop failed: {}", e)))?; // Delete the schema record sqlx::query!( "DELETE FROM schemas WHERE id = $1", schema_id ) .execute(&mut *transaction) .await .map_err(|e| Status::internal(format!("Schema 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), }) }