From: Michael Paquier Date: Tue, 25 Feb 2025 01:07:24 +0000 (+0900) Subject: psql: Add pipeline status to prompt and some state variables X-Git-Tag: REL_18_BETA1~765 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=3ce357584e795762aa6dc45fafc21dccea7e5ec6;p=postgresql.git psql: Add pipeline status to prompt and some state variables This commit adds %P to psql prompts, able to report the status of a pipeline depending on PQpipelineStatus(): on, off or abort. The following variables are added to report the state of an ongoing pipeline: - PIPELINE_SYNC_COUNT: reports the number of piped syncs. - PIPELINE_COMMAND_COUNT: reports the number of piped commands, a command being either \bind, \bind_named, \close or \parse. - PIPELINE_RESULT_COUNT: reports the results available to read with \getresults. These variables can be used with \echo or in a prompt, using "%:name:" in PROMPT1, PROMPT2 or PROMPT3. Some basic regression tests are added for these. The suggestion to use variables to show the details about the status counters comes from me. The original patch proposed was less extensible, hardcoding the output in the prompt. Author: Anthonin Bonnefoy Discussion: https://postgr.es/m/CAO6_XqroE7JuMEm1sWz55rp9fAYX2JwmcP_3m_v51vnOFdsLiQ@mail.gmail.com --- diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index 3edbd65e46c..cedccc14129 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -3728,6 +3728,12 @@ testdb=> \setenv LESS -imx4F generate one result to get. + + When pipeline mode is active, a dedicated prompt variable is available + to report the pipeline status. + See for more details + + Example: @@ -4502,6 +4508,39 @@ bar + + PIPELINE_COMMAND_COUNT + + + The number of commands generated by \bind, + \bind_named, \close or + \parse queued in an ongoing pipeline. + + + + + + PIPELINE_RESULT_COUNT + + + The number of commands of an ongoing pipeline that were followed + by either a \flushrequest or a + \syncpipeline, forcing the server to send the + results. These results can be retrieved with + \getresults. + + + + + + PIPELINE_SYNC_COUNT + + + The number of sync messages queued in an ongoing pipeline. + + + + PORT @@ -4901,6 +4940,17 @@ testdb=> INSERT INTO my_table VALUES (:'content'); + + %P + + + Pipeline status: off when not in a pipeline, + on when in an ongoing pipeline or + abort when in an aborted pipeline. + + + + %R diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index bc8c40898f7..ed340a466f9 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -524,6 +524,26 @@ SetShellResultVariables(int wait_result) } +/* + * Set special pipeline variables + * - PIPELINE_SYNC_COUNT: The number of piped syncs + * - PIPELINE_COMMAND_COUNT: The number of piped commands + * - PIPELINE_RESULT_COUNT: The number of results available to read + */ +static void +SetPipelineVariables(void) +{ + char buf[32]; + + snprintf(buf, sizeof(buf), "%d", pset.piped_syncs); + SetVariable(pset.vars, "PIPELINE_SYNC_COUNT", buf); + snprintf(buf, sizeof(buf), "%d", pset.piped_commands); + SetVariable(pset.vars, "PIPELINE_COMMAND_COUNT", buf); + snprintf(buf, sizeof(buf), "%d", pset.available_results); + SetVariable(pset.vars, "PIPELINE_RESULT_COUNT", buf); +} + + /* * ClearOrSaveResult * @@ -1661,6 +1681,8 @@ ExecQueryAndProcessResults(const char *query, CheckConnection(); + SetPipelineVariables(); + return -1; } @@ -1669,8 +1691,10 @@ ExecQueryAndProcessResults(const char *query, { /* * We are in a pipeline and have not reached the pipeline end, or - * there was no request to read pipeline results, exit. + * there was no request to read pipeline results. Update the psql + * variables tracking the pipeline activity and exit. */ + SetPipelineVariables(); return 1; } @@ -2105,6 +2129,7 @@ ExecQueryAndProcessResults(const char *query, Assert(pset.available_results == 0); } Assert(pset.requested_results == 0); + SetPipelineVariables(); /* may need this to recover from conn loss during COPY */ if (!CheckConnection()) diff --git a/src/bin/psql/prompt.c b/src/bin/psql/prompt.c index 08a14feb3c3..3aa7d2d06c8 100644 --- a/src/bin/psql/prompt.c +++ b/src/bin/psql/prompt.c @@ -31,6 +31,7 @@ * sockets, "[local:/dir/name]" if not default * %m - like %M, but hostname only (before first dot), or always "[local]" * %p - backend pid + * %P - pipeline status: on, off or abort * %> - database server port number * %n - database user name * %s - service @@ -181,6 +182,19 @@ get_prompt(promptStatus_t status, ConditionalStack cstack) snprintf(buf, sizeof(buf), "%d", pid); } break; + /* pipeline status */ + case 'P': + { + PGpipelineStatus status = PQpipelineStatus(pset.db); + + if (status == PQ_PIPELINE_ON) + strlcpy(buf, "on", sizeof(buf)); + else if (status == PQ_PIPELINE_ABORTED) + strlcpy(buf, "abort", sizeof(buf)); + else + strlcpy(buf, "off", sizeof(buf)); + break; + } case '0': case '1': diff --git a/src/bin/psql/startup.c b/src/bin/psql/startup.c index 703f3f582c1..5018eedf1e5 100644 --- a/src/bin/psql/startup.c +++ b/src/bin/psql/startup.c @@ -205,6 +205,11 @@ main(int argc, char *argv[]) SetVariable(pset.vars, "PROMPT3", DEFAULT_PROMPT3); SetVariableBool(pset.vars, "SHOW_ALL_RESULTS"); + /* Initialize pipeline variables */ + SetVariable(pset.vars, "PIPELINE_SYNC_COUNT", "0"); + SetVariable(pset.vars, "PIPELINE_COMMAND_COUNT", "0"); + SetVariable(pset.vars, "PIPELINE_RESULT_COUNT", "0"); + parse_psql_options(argc, argv, &options); /* diff --git a/src/test/regress/expected/psql_pipeline.out b/src/test/regress/expected/psql_pipeline.out index f4603d2b66a..3df2415a840 100644 --- a/src/test/regress/expected/psql_pipeline.out +++ b/src/test/regress/expected/psql_pipeline.out @@ -57,12 +57,24 @@ SELECT $1, $2 \bind 'val2' 'val3' \g -- Send multiple syncs \startpipeline +\echo :PIPELINE_COMMAND_COUNT +0 +\echo :PIPELINE_SYNC_COUNT +0 +\echo :PIPELINE_RESULT_COUNT +0 SELECT $1 \bind 'val1' \g \syncpipeline \syncpipeline SELECT $1, $2 \bind 'val2' 'val3' \g \syncpipeline SELECT $1, $2 \bind 'val4' 'val5' \g +\echo :PIPELINE_COMMAND_COUNT +1 +\echo :PIPELINE_SYNC_COUNT +3 +\echo :PIPELINE_RESULT_COUNT +2 \endpipeline ?column? ---------- @@ -303,13 +315,21 @@ SELECT $1 \bind 2 \g SELECT $1 \bind 1 \g SELECT $1 \bind 2 \g SELECT $1 \bind 3 \g +\echo :PIPELINE_SYNC_COUNT +0 \syncpipeline +\echo :PIPELINE_SYNC_COUNT +1 +\echo :PIPELINE_RESULT_COUNT +3 \getresults 1 ?column? ---------- 1 (1 row) +\echo :PIPELINE_RESULT_COUNT +2 SELECT $1 \bind 4 \g \getresults 3 ?column? @@ -322,6 +342,8 @@ SELECT $1 \bind 4 \g 3 (1 row) +\echo :PIPELINE_RESULT_COUNT +0 \endpipeline ?column? ---------- diff --git a/src/test/regress/sql/psql_pipeline.sql b/src/test/regress/sql/psql_pipeline.sql index ec62e6c5f24..6517ebb71f8 100644 --- a/src/test/regress/sql/psql_pipeline.sql +++ b/src/test/regress/sql/psql_pipeline.sql @@ -27,12 +27,18 @@ SELECT $1, $2 \bind 'val2' 'val3' \g -- Send multiple syncs \startpipeline +\echo :PIPELINE_COMMAND_COUNT +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT SELECT $1 \bind 'val1' \g \syncpipeline \syncpipeline SELECT $1, $2 \bind 'val2' 'val3' \g \syncpipeline SELECT $1, $2 \bind 'val4' 'val5' \g +\echo :PIPELINE_COMMAND_COUNT +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT \endpipeline -- \startpipeline should not have any effect if already in a pipeline. @@ -174,10 +180,15 @@ SELECT $1 \bind 2 \g SELECT $1 \bind 1 \g SELECT $1 \bind 2 \g SELECT $1 \bind 3 \g +\echo :PIPELINE_SYNC_COUNT \syncpipeline +\echo :PIPELINE_SYNC_COUNT +\echo :PIPELINE_RESULT_COUNT \getresults 1 +\echo :PIPELINE_RESULT_COUNT SELECT $1 \bind 4 \g \getresults 3 +\echo :PIPELINE_RESULT_COUNT \endpipeline -- \syncpipeline count as one command to fetch for \getresults.