postgres.git / summary / log / commit / refs

commit    c00637b5fdbf756d48021db82f1f9a877429e2a7
Author:   Michael Paquier <michael@paquier.xyz>
Date:     Fri Oct 03 05:04:00 2025 +0000
First released in: 13.23, 14.20, 15.15, 16.11, 17.7, 18.1

    pgbench: Fail cleanly when finding a COPY result state
    
    Currently, pgbench aborts when a COPY response is received in
    readCommandResponse().  However, as PQgetResult() returns an empty
    result when there is no asynchronous result, through getCopyResult(),
    the logic done at the end of readCommandResponse() for the error path
    leads to an infinite loop.
    
    This commit forcefully exits the COPY state with PQendcopy() before
    moving to the error handler when fiding a COPY state, avoiding the
    infinite loop.  The COPY protocol is not supported by pgbench anyway, as
    an error is assumed in this case, so giving up is better than having the
    tool be stuck forever.  pgbench was interruptible in this state.
    
    A TAP test is added to check that an error happens if trying to use
    COPY.
    
    Author: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
    Discussion: https://postgr.es/m/CAO6_XqpHyF2m73ifV5a=5jhXxH2chk=XrgefY+eWWPe2Eft3=A@mail.gmail.com
    Backpatch-through: 13


src/bin/pgbench/pgbench.c | 14 ++++++++++++++ src/bin/pgbench/t/001_pgbench_with_server.pl | 11 +++++++++++ 2 files changed, 25 insertions(+) diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index fa15c84ba8d..afe3ce65fb7 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -3359,6 +3359,20 @@ readCommandResponse(CState *st, MetaCommand meta, char *varprefix) PQresultErrorMessage(res)); break; + case PGRES_COPY_IN: + case PGRES_COPY_OUT: + case PGRES_COPY_BOTH: + pg_log_error("COPY is not supported in pgbench, aborting"); + + /* + * We need to exit the copy state. Otherwise, PQgetResult() + * will always return an empty PGresult as an effect of + * getCopyResult(), leading to an infinite loop in the error + * cleanup done below. + */ + PQendcopy(st->con); + goto error; + case PGRES_NONFATAL_ERROR: case PGRES_FATAL_ERROR: st->estatus = getSQLErrorStatus(PQresultErrorField(res, diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index 7dd78940300..f61dcf68234 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -1810,6 +1810,17 @@ update counter set i = i+1 returning i \gset } }); +# Test copy in pgbench +$node->pgbench( + '-t 10', + 2, + [], + [ qr{COPY is not supported in pgbench, aborting} ], + 'Test copy in script', + { + '001_copy' => q{ COPY pgbench_accounts FROM stdin } + }); + # Clean up $node->safe_psql('postgres', 'DROP TABLE counter;'); [parent: fc295beb7b74]