Skip to content

Commit 17caf66

Browse files
committed
psql: Add \sendpipeline to send query buffers while in a pipeline
In the initial pipeline support for psql added in 41625ab, \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
1 parent da72269 commit 17caf66

File tree

8 files changed

+305
-225
lines changed

8 files changed

+305
-225
lines changed

doc/src/sgml/ref/psql-ref.sgml

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3677,6 +3677,7 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
36773677

36783678
<varlistentry id="app-psql-meta-command-pipeline">
36793679
<term><literal>\startpipeline</literal></term>
3680+
<term><literal>\sendpipeline</literal></term>
36803681
<term><literal>\syncpipeline</literal></term>
36813682
<term><literal>\endpipeline</literal></term>
36823683
<term><literal>\flushrequest</literal></term>
@@ -3701,10 +3702,10 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
37013702
queries need to be sent using the meta-commands
37023703
<literal>\bind</literal>, <literal>\bind_named</literal>,
37033704
<literal>\close</literal> or <literal>\parse</literal>. While a
3704-
pipeline is ongoing, <literal>\g</literal> will append the current
3705-
query buffer to the pipeline. Other meta-commands like
3706-
<literal>\gx</literal> or <literal>\gdesc</literal> are not allowed
3707-
in pipeline mode.
3705+
pipeline is ongoing, <literal>\sendpipeline</literal> will append the
3706+
current query buffer to the pipeline. Other meta-commands like
3707+
<literal>\g</literal>, <literal>\gx</literal> or <literal>\gdesc</literal>
3708+
are not allowed in pipeline mode.
37083709
</para>
37093710

37103711
<para>
@@ -3738,7 +3739,7 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
37383739
Example:
37393740
<programlisting>
37403741
\startpipeline
3741-
SELECT 1 \bind \g
3742+
SELECT 1 \bind \sendpipeline
37423743
\flushrequest
37433744
\getresults
37443745
\endpipeline

src/bin/psql/command.c

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ static backslashResult exec_command_quit(PsqlScanState scan_state, bool active_b
131131
static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
132132
PQExpBuffer query_buf);
133133
static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch);
134+
static backslashResult exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch);
134135
static backslashResult exec_command_set(PsqlScanState scan_state, bool active_branch);
135136
static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
136137
const char *cmd);
@@ -417,6 +418,8 @@ exec_command(const char *cmd,
417418
status = exec_command_reset(scan_state, active_branch, query_buf);
418419
else if (strcmp(cmd, "s") == 0)
419420
status = exec_command_s(scan_state, active_branch);
421+
else if (strcmp(cmd, "sendpipeline") == 0)
422+
status = exec_command_sendpipeline(scan_state, active_branch);
420423
else if (strcmp(cmd, "set") == 0)
421424
status = exec_command_set(scan_state, active_branch);
422425
else if (strcmp(cmd, "setenv") == 0)
@@ -1734,10 +1737,9 @@ exec_command_g(PsqlScanState scan_state, bool active_branch, const char *cmd)
17341737

17351738
if (status == PSQL_CMD_SKIP_LINE && active_branch)
17361739
{
1737-
if (strcmp(cmd, "gx") == 0 &&
1738-
PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF)
1740+
if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF)
17391741
{
1740-
pg_log_error("\\gx not allowed in pipeline mode");
1742+
pg_log_error("\\%s not allowed in pipeline mode", cmd);
17411743
clean_extended_state();
17421744
free(fname);
17431745
return PSQL_CMD_ERROR;
@@ -2776,6 +2778,43 @@ exec_command_s(PsqlScanState scan_state, bool active_branch)
27762778
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
27772779
}
27782780

2781+
/*
2782+
* \sendpipeline -- send an extended query to an ongoing pipeline
2783+
*/
2784+
static backslashResult
2785+
exec_command_sendpipeline(PsqlScanState scan_state, bool active_branch)
2786+
{
2787+
backslashResult status = PSQL_CMD_SKIP_LINE;
2788+
2789+
if (active_branch)
2790+
{
2791+
if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF)
2792+
{
2793+
if (pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PREPARED ||
2794+
pset.send_mode == PSQL_SEND_EXTENDED_QUERY_PARAMS)
2795+
{
2796+
status = PSQL_CMD_SEND;
2797+
}
2798+
else
2799+
{
2800+
pg_log_error("\\sendpipeline must be used after \\bind or \\bind_named");
2801+
clean_extended_state();
2802+
return PSQL_CMD_ERROR;
2803+
}
2804+
}
2805+
else
2806+
{
2807+
pg_log_error("\\sendpipeline not allowed outside of pipeline mode");
2808+
clean_extended_state();
2809+
return PSQL_CMD_ERROR;
2810+
}
2811+
}
2812+
else
2813+
ignore_slash_options(scan_state);
2814+
2815+
return status;
2816+
}
2817+
27792818
/*
27802819
* \set -- set variable
27812820
*/

src/bin/psql/help.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,7 @@ slashUsage(unsigned short int pager)
181181
HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n");
182182
HELP0(" \\parse STMT_NAME create a prepared statement\n");
183183
HELP0(" \\q quit psql\n");
184+
HELP0(" \\sendpipeline send an extended query to an ongoing pipeline\n");
184185
HELP0(" \\startpipeline enter pipeline mode\n");
185186
HELP0(" \\syncpipeline add a synchronisation point to an ongoing pipeline\n");
186187
HELP0(" \\watch [[i=]SEC] [c=N] [m=MIN]\n"

src/bin/psql/tab-complete.in.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,7 +1895,8 @@ psql_completion(const char *text, int start, int end)
18951895
"\\parse", "\\password", "\\print", "\\prompt", "\\pset",
18961896
"\\qecho", "\\quit",
18971897
"\\reset",
1898-
"\\s", "\\set", "\\setenv", "\\sf", "\\startpipeline", "\\sv", "\\syncpipeline",
1898+
"\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
1899+
"\\startpipeline", "\\sv", "\\syncpipeline",
18991900
"\\t", "\\T", "\\timing",
19001901
"\\unset",
19011902
"\\x",

src/test/regress/expected/psql.out

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4706,6 +4706,7 @@ invalid command \lo
47064706
\q
47074707
\reset
47084708
\s arg1
4709+
\sendpipeline
47094710
\set arg1 arg2 arg3 arg4 arg5 arg6 arg7
47104711
\setenv arg1 arg2
47114712
\sf whole_line

0 commit comments

Comments
 (0)