Part of #8597 (Phase 3 — later feature integration).
Problem
PG19 adds a new IO option to EXPLAIN. Citus does not forward it to worker nodes, so for a distributed query the option is silently dropped: the user gets a plan with no worker IO information and no error or warning.
Evidence
Upstream (19beta2):
src/include/commands/explain_state.h:58 — bool io; /* print info about IO (prefetch, ...) */, new in PG19.
src/backend/commands/explain_state.c:165 — parses the "io" option into es->io.
Citus:
src/backend/distributed/planner/multi_explain.c:1226-1259 — BuildRemoteExplainQuery() builds the worker EXPLAIN string from a hand-maintained option list.
- Grepping that file for
es->io returns nothing, so the option is never emitted for workers.
Because the option list is an allowlist rather than a passthrough, every new upstream EXPLAIN option defaults to being dropped rather than rejected.
Proposed fix
Add a #if PG_VERSION_NUM >= PG_VERSION_19 branch to BuildRemoteExplainQuery(), mirroring the existing PG17 MEMORY / SERIALIZE guards already in that function at lines 1231-1233, 1240-1242 and 1251-1254. Same shape, no new mechanism.
Related check in the same area
explain_state.c:84,100-101,185 — es->buffers = (buffers_set) ? es->buffers : es->analyze;. In PG19 BUFFERS now defaults on whenever ANALYZE is used. Worth confirming that the pg19-support expected outputs already absorbed this; several stabilization PRs touched EXPLAIN output (#8660, #8680, #8734), so it may already be covered.
Not yet proven
The analysis above is from source shape. It has not been confirmed at runtime that EXPLAIN (ANALYZE, IO) on a distributed table degrades silently rather than erroring. Reproducing that on a live PG19 cluster should be the first step.
Scope
src/backend/distributed/planner/multi_explain.c, plus expected-output updates. Small.
Part of #8597 (Phase 3 — later feature integration).
Problem
PG19 adds a new
IOoption toEXPLAIN. Citus does not forward it to worker nodes, so for a distributed query the option is silently dropped: the user gets a plan with no worker IO information and no error or warning.Evidence
Upstream (19beta2):
src/include/commands/explain_state.h:58—bool io; /* print info about IO (prefetch, ...) */, new in PG19.src/backend/commands/explain_state.c:165— parses the"io"option intoes->io.Citus:
src/backend/distributed/planner/multi_explain.c:1226-1259—BuildRemoteExplainQuery()builds the workerEXPLAINstring from a hand-maintained option list.es->ioreturns nothing, so the option is never emitted for workers.Because the option list is an allowlist rather than a passthrough, every new upstream
EXPLAINoption defaults to being dropped rather than rejected.Proposed fix
Add a
#if PG_VERSION_NUM >= PG_VERSION_19branch toBuildRemoteExplainQuery(), mirroring the existing PG17MEMORY/SERIALIZEguards already in that function at lines 1231-1233, 1240-1242 and 1251-1254. Same shape, no new mechanism.Related check in the same area
explain_state.c:84,100-101,185—es->buffers = (buffers_set) ? es->buffers : es->analyze;. In PG19BUFFERSnow defaults on wheneverANALYZEis used. Worth confirming that thepg19-supportexpected outputs already absorbed this; several stabilization PRs touched EXPLAIN output (#8660, #8680, #8734), so it may already be covered.Not yet proven
The analysis above is from source shape. It has not been confirmed at runtime that
EXPLAIN (ANALYZE, IO)on a distributed table degrades silently rather than erroring. Reproducing that on a live PG19 cluster should be the first step.Scope
src/backend/distributed/planner/multi_explain.c, plus expected-output updates. Small.