diff options
author | Michael Paquier <michael@paquier.xyz> | 2025-03-18 09:41:21 +0900 |
---|---|---|
committer | Michael Paquier <michael@paquier.xyz> | 2025-03-18 09:41:21 +0900 |
commit | 17caf6644546eccb4a1f6e0137ea1d0f58da8c16 (patch) | |
tree | a753c92789023f00ab93edc3323b9fe196919fbf /src/bin/psql | |
parent | da7226993fd4b73d8b40abb7167d124eada97f2e (diff) | |
download | postgresql-17caf6644546eccb4a1f6e0137ea1d0f58da8c16.tar.gz postgresql-17caf6644546eccb4a1f6e0137ea1d0f58da8c16.zip |
psql: Add \sendpipeline to send query buffers while in a pipeline
In the initial pipeline support for psql added in 41625ab8ea3d, \g was
used as the way to push extended query into an ongoing pipeline. \gx
was blocked.
These two meta-commands have format-related options that can be applied
when fetching a query result (expanded, etc.). As the results of a
pipeline are fetched asynchronously, not at the moment of the
meta-command execution but at the moment of a \getresults or a
\endpipeline, authorizing \g while blocking \gx leads to a confusing
implementation, making one think that psql should be smart enough to
remember the output format options defined from the time when \g or \gx
were executed. Doing so would lead to more code complications when
retrieving a batch of results. There is an extra argument other than
simplicity here: the output format options defined at the point of a
\getresults or a \endpipeline execution should be what affect the output
format for a batch of results.
To avoid any confusion, we have settled to the introduction of a new
meta-command called \sendpipeline, replacing \g when within a pipeline.
An advantage of this design is that it is possible to add new options
specific to pipelines when sending a query buffer, independent of \g
and \gx, should it prove to be necessary.
Most of the changes of this commit happen in the regression tests, where
\g is replaced by \sendpipeline. More tests are added to check that \g
is not allowed.
Per discussion between the author, Daniel Vérité and me.
Author: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
Discussion: https://postgr.es/m/ad4b9f1a-f7fe-4ab8-8546-90754726d0be@manitou-mail.org
Diffstat (limited to 'src/bin/psql')
-rw-r--r-- | src/bin/psql/command.c | 45 | ||||
-rw-r--r-- | src/bin/psql/help.c | 1 | ||||
-rw-r--r-- | src/bin/psql/tab-complete.in.c | 3 |
3 files changed, 45 insertions, 4 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index fb0b27568c5..a87ff7e4597 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -131,6 +131,7 @@ static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_b static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch, PQExpBuffer query_buf); static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch); +static backslashResult exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch); static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch, const char *cmd); @@ -417,6 +418,8 @@ exec_command(const char *cmd, status = exec_command_reset(scan_state, active_branch, query_buf); else if (strcmp(cmd, "s") == 0) status = exec_command_s(scan_state, active_branch); + else if (strcmp(cmd, "sendpipeline") == 0) + status = exec_command_sendpipeline(scan_state, active_branch); else if (strcmp(cmd, "set") == 0) status = exec_command_set(scan_state, active_branch); else if (strcmp(cmd, "setenv") == 0) @@ -1734,10 +1737,9 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd) if (status == PSQL_CMD_SKIP_LINE && active_branch) { - if (strcmp(cmd, "gx") == 0 && - PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) { - pg_log_error("\\gx not allowed in pipeline mode"); + pg_log_error("\\%s not allowed in pipeline mode", cmd); clean_extended_state(); free(fname); return PSQL_CMD_ERROR; @@ -2777,6 +2779,43 @@ exec_command_s(PsqlScanState scan_state, bool active_branch) } /* + * \sendpipeline -- send an extended query to an ongoing pipeline + */ +static backslashResult +exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch) +{ + backslashResult status = PSQL_CMD_SKIP_LINE; + + if (active_branch) + { + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + if (pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PREPARED || + pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PARAMS) + { + status = PSQL_CMD_SEND; + } + else + { + pg_log_error("\\sendpipeline must be used after \\bind or \\bind_named"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } + } + else + { + pg_log_error("\\sendpipeline not allowed outside of pipeline mode"); + clean_extended_state(); + return PSQL_CMD_ERROR; + } + } + else + ignore_slash_options(scan_state); + + return status; +} + +/* * \set -- set variable */ static backslashResult diff --git a/src/bin/psql/help.c b/src/bin/psql/help.c index 714b8619233..e47cad24de9 100644 --- a/src/bin/psql/help.c +++ b/src/bin/psql/help.c @@ -181,6 +181,7 @@ slashUsage(unsigned short int pager) HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n"); HELP0(" \\parse STMT_NAME create a prepared statement\n"); HELP0(" \\q quit psql\n"); + HELP0(" \\sendpipeline send an extended query to an ongoing pipeline\n"); HELP0(" \\startpipeline enter pipeline mode\n"); HELP0(" \\syncpipeline add a synchronisation point to an ongoing pipeline\n"); HELP0(" \\watch [[i=]SEC] [c=N] [m=MIN]\n" diff --git a/src/bin/psql/tab-complete.in.c b/src/bin/psql/tab-complete.in.c index 8432be641ac..9a4d993e2bc 100644 --- a/src/bin/psql/tab-complete.in.c +++ b/src/bin/psql/tab-complete.in.c @@ -1895,7 +1895,8 @@ psql_completion(const char *text, int start, int end) "\\parse", "\\password", "\\print", "\\prompt", "\\pset", "\\qecho", "\\quit", "\\reset", - "\\s", "\\set", "\\setenv", "\\sf", "\\startpipeline", "\\sv", "\\syncpipeline", + "\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf", + "\\startpipeline", "\\sv", "\\syncpipeline", "\\t", "\\T", "\\timing", "\\unset", "\\x", |