pg_stat_statements stores WITH HOLD cursor query with literals

From: Gaurav Singh <gaurav(dot)singh(at)yugabyte(dot)com>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Subject: pg_stat_statements stores WITH HOLD cursor query with literals
Date: 2026-10-12 20:10:34
Message-ID: CAEcQ1bZrgwKsauC=03otebkLk77Zc_hYNjhTP3OUdpXs++u+BA@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

Hi,

On PostgreSQL 19beta1, pg_stat_statements can store the query of a
WITH HOLD cursor as a separate top-level entry, without normalizing
its constants.

Repro (shared_preload_libraries = 'pg_stat_statements'):

CREATE EXTENSION pg_stat_statements;
LOAD 'auto_explain';
SET auto_explain.log_min_duration = 0;
SELECT pg_stat_statements_reset();
DECLARE c CURSOR WITH HOLD FOR SELECT 1;
CLOSE c;
SELECT toplevel, calls, query FROM pg_stat_statements
WHERE query LIKE 'DECLARE%';

toplevel | calls | query
----------+-------+------------------------------------------
t | 1 | DECLARE c CURSOR WITH HOLD FOR SELECT $1
t | 1 | DECLARE c CURSOR WITH HOLD FOR SELECT 1;
Without auto_explain, only the first row appears. Without auto_explain
but with pg_stat_statements.track = 'all', the second row appears too.

The cursor's query starts inside DECLARE (nesting level 1), but a
WITH HOLD cursor finishes it at commit (nesting level 0).
pgss_ExecutorEnd stores any query that has a queryId and query_instr,
even when pg_stat_statements did not request query_instr itself or
requested it at another nesting level. It then finds no normalized
entry, so it stores the raw text.

Thanks,
Gaurav Singh

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Sami Imseih 2026-10-12 21:50:45 Re: pg_stat_statements stores WITH HOLD cursor query with literals
Previous Message Andrey Rachitskiy 2026-10-12 17:54:23 Re: BUG #19752: GROUP BY on a constant and a cast to a length-limited array type crashes the server while planning