Table Function Scan can report incorrect "Maximum Storage" in EXPLAIN

Started by Tatsuya Kawata21 days ago3 messageshackers
Beta feature

Hackorum builds and tests every patch posted to the lists, not only commitfest submissions. This is Hackorum's own CI rather than the PostgreSQL project's, and it is still under testing - please report anything that looks wrong.

won't retrysuccessCI history

This thread has been committed, so CI has stopped here. Anything below is the last result it produced.

You can run a PostgreSQL built from this patch straight from Docker, with no checkout and no build:

docker run --rm -p 5432:5432 ghcr.io/hackorum-dev/postgres-patch:t254052
psql -h localhost -U postgres

Built from patchset v1 (message #1), October 04, 2026 at 03:03 PM.

Every patchset is also pushed to a branch of our PostgreSQL fork, so you can check out the same tree CI built. Without a PostgreSQL checkout:

git clone --branch t254052_1 https://github.com/hackorum-dev/postgres.git

In a checkout you already have, add the fork once:

git remote add hackorum https://github.com/hackorum-dev/postgres.git

then, for this patchset and every later one:

git fetch hackorum t254052_1 && git checkout t254052_1

Patchset v1 (message #1) is on t254052_1

Jump to latest
#1Tatsuya Kawata
kawatatatsuya0913@gmail.com

Hi,

40708acd65 added memory/disk usage to EXPLAIN ANALYZE for Table Function
Scan nodes. However, when the node is rescanned with changed
parameters, ExecReScanTableFuncScan() calls tuplestore_end(), so the
statistics of the earlier rescans are lost and only those of the final
rescan are reported.

This is the same problem that David reported for Material nodes in [1]/messages/by-id/CAApHDvoa55vcRth05Ozu5be4FawgTH-aCsZ5=Z+_UXTUzUxdQg@mail.gmail.com,
as also mentioned in [2]/messages/by-id/CAApHDvoFPyT10sRDY+bH1MOwHwWNnBQKR7xgEePDke15-EkMkQ@mail.gmail.com.

For example:

EXPLAIN ANALYZE
SELECT count(*)
FROM (VALUES ((SELECT jsonb_agg(g) FROM generate_series(1, 100000) g)),
('[1]/messages/by-id/CAApHDvoa55vcRth05Ozu5be4FawgTH-aCsZ5=Z+_UXTUzUxdQg@mail.gmail.com'::jsonb)) v(j),
LATERAL JSON_TABLE(v.j, '$[*]' COLUMNS (x int PATH '$')) jt;

The Table Function Scan node reports the following:

larger document first: master Memory 17kB patched Disk 4096kB
smaller document first: master Disk 4096kB patched Disk 4096kB

Regards,
Tatsuya Kawata

[1]: /messages/by-id/CAApHDvoa55vcRth05Ozu5be4FawgTH-aCsZ5=Z+_UXTUzUxdQg@mail.gmail.com
/messages/by-id/CAApHDvoa55vcRth05Ozu5be4FawgTH-aCsZ5=Z+_UXTUzUxdQg@mail.gmail.com
[2]: /messages/by-id/CAApHDvoFPyT10sRDY+bH1MOwHwWNnBQKR7xgEePDke15-EkMkQ@mail.gmail.com
/messages/by-id/CAApHDvoFPyT10sRDY+bH1MOwHwWNnBQKR7xgEePDke15-EkMkQ@mail.gmail.com

Attachments:

t254052_1
v1-0001-Use-tuplestore_clear-instead-of-tuplestore_end-in-nodeTableFuncscan.c.patchapplication/octet-stream; name=v1-0001-Use-tuplestore_clear-instead-of-tuplestore_end-in-nodeTableFuncscan.c.patchDownload+17-11
#2David Rowley
dgrowleyml@gmail.com
In reply to: Tatsuya Kawata (#1)
Re: Table Function Scan can report incorrect "Maximum Storage" in EXPLAIN

On Mon, 5 Oct 2026 at 03:52, Tatsuya Kawata <kawatatatsuya0913@gmail.com> wrote:

40708acd65 added memory/disk usage to EXPLAIN ANALYZE for Table Function
Scan nodes. However, when the node is rescanned with changed
parameters, ExecReScanTableFuncScan() calls tuplestore_end(), so the
statistics of the earlier rescans are lost and only those of the final
rescan are reported.

I made a very small change so we only call tuplestore_rescan() when
the parameters don't change. The call to tuplestore_clear() rewinds
the read pointers, so there's no point in calling tuplestore_rescan()
after tuplestore_clear().

Pushed. Thanks.

David

#3Tatsuya Kawata
kawatatatsuya0913@gmail.com
In reply to: David Rowley (#2)
Re: Table Function Scan can report incorrect "Maximum Storage" in EXPLAIN

Hi David,

I made a very small change so we only call tuplestore_rescan() when
the parameters don't change. The call to tuplestore_clear() rewinds
the read pointers, so there's no point in calling tuplestore_rescan()
after tuplestore_clear().

Pushed. Thanks.

Thanks for the fix and for pushing it!

Regards,
Tatsuya Kawata