postgres.git / summary / log / commit / refs

commit    ec1d545c8f7093537ee644bb33137fff91277463
Author:   Thomas Munro <tmunro@postgresql.org>
Date:     Tue Sep 17 21:20:59 2024 +0000
First released in: 18.0, 17.0

    Allow ReadStream to be consumed as raw block numbers.
    
    Commits 041b9680 and 6377e12a changed the interface of
    scan_analyze_next_block() to take a ReadStream instead of a BlockNumber
    and a BufferAccessStrategy, and to return a value to indicate when the
    stream has run out of blocks.
    
    This caused integration problems for at least one known extension that
    uses specially encoded BlockNumber values that map to different
    underlying storage, because acquire_sample_rows() sets up the stream so
    that read_stream_next_buffer() reads blocks from the main fork of the
    relation's SMgrRelation.
    
    Provide read_stream_next_block(), as a way for such an extension to
    access the stream of raw BlockNumbers directly and forward them to its
    own ReadBuffer() calls after decoding, as it could in earlier releases.
    The new function returns the BlockNumber and BufferAccessStrategy that
    were previously passed directly to scan_analyze_next_block().
    Alternatively, an extension could wrap the stream of BlockNumbers in
    another ReadStream with a callback that performs any decoding required
    to arrive at real storage manager BlockNumber values, so that it could
    benefit from the I/O combining and concurrency provided by
    read_stream.c.
    
    Another class of table access method that does nothing in
    scan_analyze_next_block() because it is not block-oriented could use
    this function to control the number of block sampling loops.  It could
    match the previous behavior with "return read_stream_next_block(stream,
    &bas) != InvalidBlockNumber".
    
    Ongoing work is expected to provide better ANALYZE support for table
    access methods that don't behave like heapam with respect to storage
    blocks, but that will be for future releases.
    
    Back-patch to 17.
    
    Reported-by: Mats Kindahl <mats@timescale.com>
    Reviewed-by: Mats Kindahl <mats@timescale.com>
    Discussion: https://postgr.es/m/CA%2B14425%2BCcm07ocG97Fp%2BFrD9xUXqmBKFvecp0p%2BgV2YYR258Q%40mail.gmail.com


src/backend/storage/aio/read_stream.c | 14 ++++++++++++++ src/include/storage/read_stream.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/backend/storage/aio/read_stream.c b/src/backend/storage/aio/read_stream.c index a6c50b2ae24..9b962c301bf 100644 --- a/src/backend/storage/aio/read_stream.c +++ b/src/backend/storage/aio/read_stream.c @@ -731,6 +731,20 @@ read_stream_next_buffer(ReadStream *stream, void **per_buffer_data) return buffer; } +/* + * Transitional support for code that would like to perform or skip reads + * itself, without using the stream. Returns, and consumes, the next block + * number that would be read by the stream's look-ahead algorithm, or + * InvalidBlockNumber if the end of the stream is reached. Also reports the + * strategy that would be used to read it. + */ +BlockNumber +read_stream_next_block(ReadStream *stream, BufferAccessStrategy *strategy) +{ + *strategy = stream->ios[0].op.strategy; + return read_stream_get_block(stream, NULL); +} + /* * Reset a read stream by releasing any queued up buffers, allowing the stream * to be used again for different blocks. This can be used to clear an diff --git a/src/include/storage/read_stream.h b/src/include/storage/read_stream.h index f676d2cc20a..7b9005e87bc 100644 --- a/src/include/storage/read_stream.h +++ b/src/include/storage/read_stream.h @@ -57,6 +57,8 @@ extern ReadStream *read_stream_begin_relation(int flags, void *callback_private_data, size_t per_buffer_data_size); extern Buffer read_stream_next_buffer(ReadStream *stream, void **per_buffer_data); +extern BlockNumber read_stream_next_block(ReadStream *stream, + BufferAccessStrategy *strategy); extern void read_stream_reset(ReadStream *stream); extern void read_stream_end(ReadStream *stream); [parent: f7567f9e53d7]