diff --git a/src-tauri/src/drivers/postgres/explain.rs b/src-tauri/src/drivers/postgres/explain.rs index 4d5a0822..46e338fc 100644 --- a/src-tauri/src/drivers/postgres/explain.rs +++ b/src-tauri/src/drivers/postgres/explain.rs @@ -29,8 +29,18 @@ pub async fn explain_query( return Err("EXPLAIN returned no output".into()); } - // PostgreSQL returns a single row with a single text column containing JSON - let plan_json_str: String = rows[0].try_get(0).map_err(|e| format_pg_error(&e))?; + // `EXPLAIN (FORMAT JSON)` on real PostgreSQL returns a column of type + // `json` (not `text`), so reading it as `String` fails with + // "error deserializing column 0". Read it as a `serde_json::Value` and + // re-serialize. Some Postgres-compatible engines hand back a plain `text` + // column instead, so fall back to reading the raw string in that case. + let plan_json_str = match rows[0].try_get::<_, serde_json::Value>(0) { + Ok(value) => value.to_string(), + Err(json_err) => rows[0].try_get::<_, String>(0).map_err(|e| { + log::debug!("EXPLAIN json read failed ({json_err}); text read also failed"); + format_pg_error(&e) + })?, + }; let mut plan = parse_postgres_json(&plan_json_str)?; plan.original_query = query.to_string();