Any query has to have a known target in plpgsql (or you can throw the result away with a PERFORM
statement). So you can do:
CREATE OR REPLACE FUNCTION fx(text)
RETURNS void AS $$
DECLARE t text;
BEGIN
FOR t IN EXPLAIN ANALYZE SELECT * FROM foo WHERE v = $1
LOOP
RAISE NOTICE '%', t;
END LOOP;
END;
$$ LANGUAGE plpgsql;
postgres=# SELECT fx('1');
NOTICE: Seq Scan on foo (cost=0.00..1.18 rows=1 width=3) (actual time=0.024..0.024 rows=0 loops=1)
NOTICE: Filter: ((v)::text = '1'::text)
NOTICE: Rows Removed by Filter: 14
NOTICE: Planning time: 0.103 ms
NOTICE: Total runtime: 0.065 ms
fx
────
(1 row)
Another possibility to get the plan for embedded SQL is using a prepared statement:
postgres=# PREPARE xx(text) AS SELECT * FROM foo WHERE v = $1;
PREPARE
Time: 0.810 ms
postgres=# EXPLAIN ANALYZE EXECUTE xx('1');
QUERY PLAN
─────────────────────────────────────────────────────────────────────────────────────────────
Seq Scan on foo (cost=0.00..1.18 rows=1 width=3) (actual time=0.030..0.030 rows=0 loops=1)
Filter: ((v)::text = '1'::text)
Rows Removed by Filter: 14
Total runtime: 0.083 ms
(4 rows)