From 07b53de700390c8bdee99ce373d84f0cdcad74d6 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Mon, 22 Jan 2024 17:48:30 +0100 Subject: [PATCH] Abort pgbench if script end is reached with an open pipeline When a pipeline is opened with \startpipeline and not closed, pgbench will either error on the next transaction with a "already in pipeline mode" error or successfully end if this was the last transaction -- despite not sending anything that was piped in the pipeline. Make it an error to reach end of script is reached while there's an open pipeline. Backpatch to 14, where pgbench got support for pipelines. Author: Anthonin Bonnefoy Reported-by: Michael Paquier Discussion: https://postgr.es/m/Za4IObZkDjrO4TcS@paquier.xyz --- src/bin/pgbench/pgbench.c | 15 +++++++++-- src/bin/pgbench/t/001_pgbench_with_server.pl | 28 ++++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/src/bin/pgbench/pgbench.c b/src/bin/pgbench/pgbench.c index cc4533aa9d7..c1134eae5b5 100644 --- a/src/bin/pgbench/pgbench.c +++ b/src/bin/pgbench/pgbench.c @@ -3756,10 +3756,21 @@ advanceConnectionState(TState *thread, CState *st, StatsData *agg) case CSTATE_START_COMMAND: command = sql_script[st->use_file].commands[st->command]; - /* Transition to script end processing if done */ + /* + * Transition to script end processing if done, but close up + * shop if a pipeline is open at this point. + */ if (command == NULL) { - st->state = CSTATE_END_TX; + if (PQpipelineStatus(st->con) == PQ_PIPELINE_OFF) + st->state = CSTATE_END_TX; + else + { + pg_log_error("client %d aborted: end of script reached with pipeline open", + st->id); + st->state = CSTATE_ABORTED; + } + break; } diff --git a/src/bin/pgbench/t/001_pgbench_with_server.pl b/src/bin/pgbench/t/001_pgbench_with_server.pl index e39d4892ab8..8c9a08e4460 100644 --- a/src/bin/pgbench/t/001_pgbench_with_server.pl +++ b/src/bin/pgbench/t/001_pgbench_with_server.pl @@ -841,6 +841,34 @@ select 1 \gset f } }); +# Try \startpipeline without \endpipeline in a single transaction +$node->pgbench( + '-t 1 -n -M extended', + 2, + [], + [qr{end of script reached with pipeline open}], + 'error: call \startpipeline without \endpipeline in a single transaction', + { + '001_pgbench_pipeline_5' => q{ +-- startpipeline only with single transaction +\startpipeline +} + }); + +# Try \startpipeline without \endpipeline +$node->pgbench( + '-t 2 -n -M extended', + 2, + [], + [qr{end of script reached with pipeline open}], + 'error: call \startpipeline without \endpipeline', + { + '001_pgbench_pipeline_6' => q{ +-- startpipeline only +\startpipeline +} + }); + # Working \startpipeline in prepared query mode with serializable $node->pgbench( '-c4 -t 10 -n -M prepared', -- 2.39.5