Re: [PATCH] Add NESTED_STATEMENTS option to EXPLAIN

Zsolt Parragi <zsolt.parragi@percona.com>

From: Zsolt Parragi <zsolt.parragi@percona.com>
To: pgsql-hackers@lists.postgresql.org
Date: 2026-05-16T11:15:34Z
Lists: pgsql-hackers
Hello!

With some initial testing I was able to find 2 server crashes with the patch.

1: error during explain

CREATE OR REPLACE FUNCTION divz_plpgsql(x int) RETURNS int LANGUAGE
plpgsql AS $$
DECLARE r int;
BEGIN
  SELECT 1/x INTO r;
  RETURN r;
END;
$$;
-- error during explain
EXPLAIN (ANALYZE, NESTED_STATEMENTS) SELECT divz_plpgsql(0);
-- run another explain
EXPLAIN (ANALYZE, NESTED_STATEMENTS) SELECT 1;
-- any next query crashes the server
SELECT 1;

2: any nested explain

CREATE FUNCTION f() RETURNS void LANGUAGE plpgsql AS $$
DECLARE r record;
BEGIN
  FOR r IN EXECUTE 'EXPLAIN (ANALYZE, NESTED_STATEMENTS) SELECT 1'
  LOOP NULL; END LOOP;
END;
$$;

EXPLAIN (ANALYZE, NESTED_STATEMENTS) SELECT f();


+		/*
+		 * Switch to TopMemoryContext so the captured plan text survives
+		 * until we print it.
+		 */
+		oldcxt = MemoryContextSwitchTo(TopMemoryContext);
...
+		ExplainBeginOutput(nes);
+		ExplainPrintPlan(nes, queryDesc);
+		ExplainEndOutput(nes);
...
+		plan_info->query_text = queryDesc->sourceText ?
+			pstrdup(queryDesc->sourceText) : pstrdup("<unknown>");

When is queryDesc freed? This seems like a memory leak.