1
0
mirror of https://github.com/postgres/postgres.git synced 2025-08-05 07:41:25 +03:00

psql: Add \sendpipeline to send query buffers while in a pipeline

In the initial pipeline support for psql added in 41625ab8ea, \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
This commit is contained in:
Michael Paquier
2025-03-18 09:41:21 +09:00
parent da7226993f
commit 17caf66445
8 changed files with 306 additions and 226 deletions

View File

@@ -3677,6 +3677,7 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
<varlistentry id="app-psql-meta-command-pipeline"> <varlistentry id="app-psql-meta-command-pipeline">
<term><literal>\startpipeline</literal></term> <term><literal>\startpipeline</literal></term>
<term><literal>\sendpipeline</literal></term>
<term><literal>\syncpipeline</literal></term> <term><literal>\syncpipeline</literal></term>
<term><literal>\endpipeline</literal></term> <term><literal>\endpipeline</literal></term>
<term><literal>\flushrequest</literal></term> <term><literal>\flushrequest</literal></term>
@@ -3701,10 +3702,10 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
queries need to be sent using the meta-commands queries need to be sent using the meta-commands
<literal>\bind</literal>, <literal>\bind_named</literal>, <literal>\bind</literal>, <literal>\bind_named</literal>,
<literal>\close</literal> or <literal>\parse</literal>. While a <literal>\close</literal> or <literal>\parse</literal>. While a
pipeline is ongoing, <literal>\g</literal> will append the current pipeline is ongoing, <literal>\sendpipeline</literal> will append the
query buffer to the pipeline. Other meta-commands like current query buffer to the pipeline. Other meta-commands like
<literal>\gx</literal> or <literal>\gdesc</literal> are not allowed <literal>\g</literal>, <literal>\gx</literal> or <literal>\gdesc</literal>
in pipeline mode. are not allowed in pipeline mode.
</para> </para>
<para> <para>
@@ -3738,7 +3739,7 @@ testdb=&gt; <userinput>\setenv LESS -imx4F</userinput>
Example: Example:
<programlisting> <programlisting>
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
\endpipeline \endpipeline

View File

@@ -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, static backslashResult exec_command_reset(PsqlScanState scan_state, bool active_branch,
PQExpBuffer query_buf); PQExpBuffer query_buf);
static backslashResult exec_command_s(PsqlScanState scan_state, bool active_branch); 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_set(PsqlScanState scan_state, bool active_branch);
static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch, static backslashResult exec_command_setenv(PsqlScanState scan_state, bool active_branch,
const char *cmd); const char *cmd);
@@ -417,6 +418,8 @@ exec_command(const char *cmd,
status = exec_command_reset(scan_state, active_branch, query_buf); status = exec_command_reset(scan_state, active_branch, query_buf);
else if (strcmp(cmd, "s") == 0) else if (strcmp(cmd, "s") == 0)
status = exec_command_s(scan_state, active_branch); 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) else if (strcmp(cmd, "set") == 0)
status = exec_command_set(scan_state, active_branch); status = exec_command_set(scan_state, active_branch);
else if (strcmp(cmd, "setenv") == 0) 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 (status == PSQL_CMD_SKIP_LINE && active_branch)
{ {
if (strcmp(cmd, "gx") == 0 && if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF)
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(); clean_extended_state();
free(fname); free(fname);
return PSQL_CMD_ERROR; return PSQL_CMD_ERROR;
@@ -2776,6 +2778,43 @@ exec_command_s(PsqlScanState scan_state, bool active_branch)
return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR; return success ? PSQL_CMD_SKIP_LINE : PSQL_CMD_ERROR;
} }
/*
* \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 * \set -- set variable
*/ */

View File

@@ -181,6 +181,7 @@ slashUsage(unsigned short int pager)
HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n"); HELP0(" \\gx [(OPTIONS)] [FILE] as \\g, but forces expanded output mode\n");
HELP0(" \\parse STMT_NAME create a prepared statement\n"); HELP0(" \\parse STMT_NAME create a prepared statement\n");
HELP0(" \\q quit psql\n"); HELP0(" \\q quit psql\n");
HELP0(" \\sendpipeline send an extended query to an ongoing pipeline\n");
HELP0(" \\startpipeline enter pipeline mode\n"); HELP0(" \\startpipeline enter pipeline mode\n");
HELP0(" \\syncpipeline add a synchronisation point to an ongoing pipeline\n"); HELP0(" \\syncpipeline add a synchronisation point to an ongoing pipeline\n");
HELP0(" \\watch [[i=]SEC] [c=N] [m=MIN]\n" HELP0(" \\watch [[i=]SEC] [c=N] [m=MIN]\n"

View File

@@ -1895,7 +1895,8 @@ psql_completion(const char *text, int start, int end)
"\\parse", "\\password", "\\print", "\\prompt", "\\pset", "\\parse", "\\password", "\\print", "\\prompt", "\\pset",
"\\qecho", "\\quit", "\\qecho", "\\quit",
"\\reset", "\\reset",
"\\s", "\\set", "\\setenv", "\\sf", "\\startpipeline", "\\sv", "\\syncpipeline", "\\s", "\\sendpipeline", "\\set", "\\setenv", "\\sf",
"\\startpipeline", "\\sv", "\\syncpipeline",
"\\t", "\\T", "\\timing", "\\t", "\\T", "\\timing",
"\\unset", "\\unset",
"\\x", "\\x",

View File

@@ -4706,6 +4706,7 @@ invalid command \lo
\q \q
\reset \reset
\s arg1 \s arg1
\sendpipeline
\set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \set arg1 arg2 arg3 arg4 arg5 arg6 arg7
\setenv arg1 arg2 \setenv arg1 arg2
\sf whole_line \sf whole_line

View File

@@ -4,7 +4,7 @@
CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT);
-- Single query -- Single query
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -13,9 +13,9 @@ SELECT $1 \bind 'val1' \g
-- Multiple queries -- Multiple queries
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -35,10 +35,10 @@ SELECT $1, $2 \bind 'val2' 'val3' \g
-- Test \flush -- Test \flush
\startpipeline \startpipeline
\flush \flush
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\flush \flush
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -63,12 +63,12 @@ SELECT $1, $2 \bind 'val2' 'val3' \g
0 0
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
0 0
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\syncpipeline \syncpipeline
\syncpipeline \syncpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\syncpipeline \syncpipeline
SELECT $1, $2 \bind 'val4' 'val5' \g SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline
\echo :PIPELINE_COMMAND_COUNT \echo :PIPELINE_COMMAND_COUNT
1 1
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
@@ -94,7 +94,7 @@ SELECT $1, $2 \bind 'val4' 'val5' \g
-- \startpipeline should not have any effect if already in a pipeline. -- \startpipeline should not have any effect if already in a pipeline.
\startpipeline \startpipeline
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -103,24 +103,24 @@ SELECT $1 \bind 'val1' \g
-- Convert an implicit transaction block to an explicit transaction block. -- Convert an implicit transaction block to an explicit transaction block.
\startpipeline \startpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 2 \g INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
\endpipeline \endpipeline
-- Multiple explicit transactions -- Multiple explicit transactions
\startpipeline \startpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
COMMIT \bind \g COMMIT \bind \sendpipeline
\endpipeline \endpipeline
-- COPY FROM STDIN -- COPY FROM STDIN
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -129,8 +129,8 @@ COPY psql_pipeline FROM STDIN \bind \g
-- COPY FROM STDIN with \flushrequest + \getresults -- COPY FROM STDIN with \flushrequest + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
?column? ?column?
@@ -142,8 +142,8 @@ message type 0x5a arrived from server while idle
\endpipeline \endpipeline
-- COPY FROM STDIN with \syncpipeline + \getresults -- COPY FROM STDIN with \syncpipeline + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
?column? ?column?
@@ -154,8 +154,8 @@ COPY psql_pipeline FROM STDIN \bind \g
\endpipeline \endpipeline
-- COPY TO STDOUT -- COPY TO STDOUT
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -168,8 +168,8 @@ copy psql_pipeline TO STDOUT \bind \g
4 test4 4 test4
-- COPY TO STDOUT with \flushrequest + \getresults -- COPY TO STDOUT with \flushrequest + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
?column? ?column?
@@ -184,8 +184,8 @@ copy psql_pipeline TO STDOUT \bind \g
\endpipeline \endpipeline
-- COPY TO STDOUT with \syncpipeline + \getresults -- COPY TO STDOUT with \syncpipeline + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
?column? ?column?
@@ -203,14 +203,14 @@ copy psql_pipeline TO STDOUT \bind \g
SELECT $1 \parse '' SELECT $1 \parse ''
SELECT $1, $2 \parse '' SELECT $1, $2 \parse ''
SELECT $2 \parse pipeline_1 SELECT $2 \parse pipeline_1
\bind_named '' 1 2 \g \bind_named '' 1 2 \sendpipeline
\bind_named pipeline_1 2 \g \bind_named pipeline_1 2 \sendpipeline
\endpipeline \endpipeline
ERROR: could not determine data type of parameter $1 ERROR: could not determine data type of parameter $1
-- \getresults displays all results preceding a \flushrequest. -- \getresults displays all results preceding a \flushrequest.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
?column? ?column?
@@ -226,8 +226,8 @@ SELECT $1 \bind 2 \g
\endpipeline \endpipeline
-- \getresults displays all results preceding a \syncpipeline. -- \getresults displays all results preceding a \syncpipeline.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
?column? ?column?
@@ -245,7 +245,7 @@ SELECT $1 \bind 2 \g
\startpipeline \startpipeline
\getresults \getresults
No pending results to get No pending results to get
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
No pending results to get No pending results to get
\flushrequest \flushrequest
@@ -259,9 +259,9 @@ No pending results to get
No pending results to get No pending results to get
-- \getresults only fetches results preceding a \flushrequest. -- \getresults only fetches results preceding a \flushrequest.
\startpipeline \startpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
?column? ?column?
---------- ----------
@@ -276,9 +276,9 @@ SELECT $1 \bind 2 \g
-- \getresults only fetches results preceding a \syncpipeline. -- \getresults only fetches results preceding a \syncpipeline.
\startpipeline \startpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
?column? ?column?
---------- ----------
@@ -294,7 +294,7 @@ SELECT $1 \bind 2 \g
-- Use pipeline with chunked results for both \getresults and \endpipeline. -- Use pipeline with chunked results for both \getresults and \endpipeline.
\startpipeline \startpipeline
\set FETCH_COUNT 10 \set FETCH_COUNT 10
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
?column? ?column?
@@ -302,7 +302,7 @@ SELECT $1 \bind 2 \g
2 2
(1 row) (1 row)
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -312,9 +312,9 @@ SELECT $1 \bind 2 \g
\unset FETCH_COUNT \unset FETCH_COUNT
-- \getresults with specific number of requested results. -- \getresults with specific number of requested results.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
SELECT $1 \bind 3 \g SELECT $1 \bind 3 \sendpipeline
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
0 0
\syncpipeline \syncpipeline
@@ -330,7 +330,7 @@ SELECT $1 \bind 3 \g
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
2 2
SELECT $1 \bind 4 \g SELECT $1 \bind 4 \sendpipeline
\getresults 3 \getresults 3
?column? ?column?
---------- ----------
@@ -354,7 +354,7 @@ SELECT $1 \bind 4 \g
\startpipeline \startpipeline
\syncpipeline \syncpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\flushrequest \flushrequest
\getresults 2 \getresults 2
\getresults 1 \getresults 1
@@ -366,9 +366,9 @@ SELECT $1 \bind 1 \g
\endpipeline \endpipeline
-- \getresults 0 should get all the results. -- \getresults 0 should get all the results.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
SELECT $1 \bind 3 \g SELECT $1 \bind 3 \sendpipeline
\syncpipeline \syncpipeline
\getresults 0 \getresults 0
?column? ?column?
@@ -398,7 +398,7 @@ cannot send pipeline when not in pipeline mode
\startpipeline \startpipeline
SELECT 1; SELECT 1;
PQsendQuery not allowed in pipeline mode PQsendQuery not allowed in pipeline mode
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -408,9 +408,9 @@ SELECT $1 \bind 'val1' \g
-- After an aborted pipeline, commands after a \syncpipeline should be -- After an aborted pipeline, commands after a \syncpipeline should be
-- displayed. -- displayed.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
?column? ?column?
@@ -421,23 +421,23 @@ ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
-- For an incorrect number of parameters, the pipeline is aborted and -- For an incorrect number of parameters, the pipeline is aborted and
-- the following queries will not be executed. -- the following queries will not be executed.
\startpipeline \startpipeline
SELECT \bind 'val1' \g SELECT \bind 'val1' \sendpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0 ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0
-- An explicit transaction with an error needs to be rollbacked after -- An explicit transaction with an error needs to be rollbacked after
-- the pipeline. -- the pipeline.
\startpipeline \startpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
\endpipeline \endpipeline
ERROR: duplicate key value violates unique constraint "psql_pipeline_pkey" ERROR: duplicate key value violates unique constraint "psql_pipeline_pkey"
DETAIL: Key (a)=(1) already exists. DETAIL: Key (a)=(1) already exists.
ROLLBACK; ROLLBACK;
-- \watch sends a simple query, something not allowed within a pipeline. -- \watch sends a simple query, something not allowed within a pipeline.
\startpipeline \startpipeline
SELECT \bind \g SELECT \bind \sendpipeline
\watch 1 \watch 1
PQsendQuery not allowed in pipeline mode PQsendQuery not allowed in pipeline mode
@@ -450,7 +450,7 @@ PQsendQuery not allowed in pipeline mode
\startpipeline \startpipeline
SELECT $1 \bind 1 \gdesc SELECT $1 \bind 1 \gdesc
synchronous command execution functions are not allowed in pipeline mode synchronous command execution functions are not allowed in pipeline mode
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -465,42 +465,63 @@ SELECT $1 as k, $2 as l \parse 'second'
\gset not allowed in pipeline mode \gset not allowed in pipeline mode
\bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j \bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j
\gset not allowed in pipeline mode \gset not allowed in pipeline mode
\bind_named '' 1 2 \g \bind_named '' 1 2 \sendpipeline
\endpipeline \endpipeline
i | j i | j
---+--- ---+---
1 | 2 1 | 2
(1 row) (1 row)
-- \gx is not allowed, pipeline should still be usable. -- \g and \gx are not allowed, pipeline should still be usable.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g
\g not allowed in pipeline mode
SELECT $1 \bind 1 \g (format=unaligned tuples_only=on)
\g not allowed in pipeline mode
SELECT $1 \bind 1 \gx SELECT $1 \bind 1 \gx
\gx not allowed in pipeline mode \gx not allowed in pipeline mode
SELECT $1 \bind 1 \gx (format=unaligned tuples_only=on)
\gx not allowed in pipeline mode
\reset \reset
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
1 1
(1 row) (1 row)
-- \gx warning should be emitted in an aborted pipeline, with -- \g and \gx warnings should be emitted in an aborted pipeline, with
-- pipeline still usable. -- pipeline still usable.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
SELECT $1 \bind 1 \g
\g not allowed in pipeline mode
SELECT $1 \bind 1 \gx SELECT $1 \bind 1 \gx
\gx not allowed in pipeline mode \gx not allowed in pipeline mode
\endpipeline \endpipeline
-- \sendpipeline is not allowed outside of a pipeline
\sendpipeline
\sendpipeline not allowed outside of pipeline mode
SELECT $1 \bind 1 \sendpipeline
\sendpipeline not allowed outside of pipeline mode
\reset
-- \sendpipeline is not allowed if not preceded by \bind or \bind_named
\startpipeline
\sendpipeline
\sendpipeline must be used after \bind or \bind_named
SELECT 1 \sendpipeline
\sendpipeline must be used after \bind or \bind_named
\endpipeline
-- \gexec is not allowed, pipeline should still be usable. -- \gexec is not allowed, pipeline should still be usable.
\startpipeline \startpipeline
SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt'
\bind_named insert_stmt \gexec \bind_named insert_stmt \gexec
\gexec not allowed in pipeline mode \gexec not allowed in pipeline mode
\bind_named insert_stmt \g \bind_named insert_stmt \sendpipeline
SELECT COUNT(*) FROM psql_pipeline \bind \g SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
?column? ?column?
------------------------------------------------------------ ------------------------------------------------------------
@@ -515,26 +536,26 @@ SELECT COUNT(*) FROM psql_pipeline \bind \g
-- After an error, pipeline is aborted and requires \syncpipeline to be -- After an error, pipeline is aborted and requires \syncpipeline to be
-- reusable. -- reusable.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
\flushrequest \flushrequest
\getresults \getresults
ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
-- Pipeline is aborted. -- Pipeline is aborted.
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
-- Sync allows pipeline to recover. -- Sync allows pipeline to recover.
\syncpipeline \syncpipeline
\getresults \getresults
Pipeline aborted, command did not run Pipeline aborted, command did not run
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
\flushrequest \flushrequest
\getresults \getresults
@@ -551,10 +572,10 @@ SELECT $1 \parse a
\endpipeline \endpipeline
-- In an aborted pipeline, \getresults 1 aborts commands one at a time. -- In an aborted pipeline, \getresults 1 aborts commands one at a time.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\syncpipeline \syncpipeline
\getresults 1 \getresults 1
ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
@@ -569,11 +590,11 @@ Pipeline aborted, command did not run
-- Test chunked results with an aborted pipeline. -- Test chunked results with an aborted pipeline.
\startpipeline \startpipeline
\set FETCH_COUNT 10 \set FETCH_COUNT 10
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\endpipeline \endpipeline
fetching results in chunked mode failed fetching results in chunked mode failed
Pipeline aborted, command did not run Pipeline aborted, command did not run
@@ -595,7 +616,7 @@ select 1;
-- Error messages accumulate and are repeated. -- Error messages accumulate and are repeated.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
SELECT 1; SELECT 1;
PQsendQuery not allowed in pipeline mode PQsendQuery not allowed in pipeline mode
SELECT 1; SELECT 1;
@@ -616,12 +637,12 @@ PQsendQuery not allowed in pipeline mode
-- commit the implicit transaction block. The first command after a -- commit the implicit transaction block. The first command after a
-- sync will not be seen as belonging to a pipeline. -- sync will not be seen as belonging to a pipeline.
\startpipeline \startpipeline
SET LOCAL statement_timeout='1h' \bind \g SET LOCAL statement_timeout='1h' \bind \sendpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
\syncpipeline \syncpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
SET LOCAL statement_timeout='2h' \bind \g SET LOCAL statement_timeout='2h' \bind \sendpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
\endpipeline \endpipeline
WARNING: SET LOCAL can only be used in transaction blocks WARNING: SET LOCAL can only be used in transaction blocks
statement_timeout statement_timeout
@@ -641,9 +662,9 @@ WARNING: SET LOCAL can only be used in transaction blocks
-- REINDEX CONCURRENTLY fails if not the first command in a pipeline. -- REINDEX CONCURRENTLY fails if not the first command in a pipeline.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -653,8 +674,8 @@ SELECT $1 \bind 2 \g
ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block
-- REINDEX CONCURRENTLY works if it is the first command in a pipeline. -- REINDEX CONCURRENTLY works if it is the first command in a pipeline.
\startpipeline \startpipeline
REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -663,25 +684,25 @@ SELECT $1 \bind 2 \g
-- Subtransactions are not allowed in a pipeline. -- Subtransactions are not allowed in a pipeline.
\startpipeline \startpipeline
SAVEPOINT a \bind \g SAVEPOINT a \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
ROLLBACK TO SAVEPOINT a \bind \g ROLLBACK TO SAVEPOINT a \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
ERROR: SAVEPOINT can only be used in transaction blocks ERROR: SAVEPOINT can only be used in transaction blocks
-- LOCK fails as the first command in a pipeline, as not seen in an -- LOCK fails as the first command in a pipeline, as not seen in an
-- implicit transaction block. -- implicit transaction block.
\startpipeline \startpipeline
LOCK psql_pipeline \bind \g LOCK psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
ERROR: LOCK TABLE can only be used in transaction blocks ERROR: LOCK TABLE can only be used in transaction blocks
-- LOCK succeeds as it is not the first command in a pipeline, -- LOCK succeeds as it is not the first command in a pipeline,
-- seen in an implicit transaction block. -- seen in an implicit transaction block.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
LOCK psql_pipeline \bind \g LOCK psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -695,12 +716,12 @@ SELECT $1 \bind 2 \g
-- VACUUM works as the first command in a pipeline. -- VACUUM works as the first command in a pipeline.
\startpipeline \startpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
-- VACUUM fails when not the first command in a pipeline. -- VACUUM fails when not the first command in a pipeline.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------
@@ -710,9 +731,9 @@ VACUUM psql_pipeline \bind \g
ERROR: VACUUM cannot run inside a transaction block ERROR: VACUUM cannot run inside a transaction block
-- VACUUM works after a \syncpipeline. -- VACUUM works after a \syncpipeline.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
\syncpipeline \syncpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
?column? ?column?
---------- ----------

View File

@@ -1074,6 +1074,7 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two;
\q \q
\reset \reset
\s arg1 \s arg1
\sendpipeline
\set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \set arg1 arg2 arg3 arg4 arg5 arg6 arg7
\setenv arg1 arg2 \setenv arg1 arg2
\sf whole_line \sf whole_line

View File

@@ -6,23 +6,23 @@ CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT);
-- Single query -- Single query
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
-- Multiple queries -- Multiple queries
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\endpipeline \endpipeline
-- Test \flush -- Test \flush
\startpipeline \startpipeline
\flush \flush
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\flush \flush
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\endpipeline \endpipeline
-- Send multiple syncs -- Send multiple syncs
@@ -30,12 +30,12 @@ SELECT $1, $2 \bind 'val2' 'val3' \g
\echo :PIPELINE_COMMAND_COUNT \echo :PIPELINE_COMMAND_COUNT
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\syncpipeline \syncpipeline
\syncpipeline \syncpipeline
SELECT $1, $2 \bind 'val2' 'val3' \g SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline
\syncpipeline \syncpipeline
SELECT $1, $2 \bind 'val4' 'val5' \g SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline
\echo :PIPELINE_COMMAND_COUNT \echo :PIPELINE_COMMAND_COUNT
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
@@ -44,39 +44,39 @@ SELECT $1, $2 \bind 'val4' 'val5' \g
-- \startpipeline should not have any effect if already in a pipeline. -- \startpipeline should not have any effect if already in a pipeline.
\startpipeline \startpipeline
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
-- Convert an implicit transaction block to an explicit transaction block. -- Convert an implicit transaction block to an explicit transaction block.
\startpipeline \startpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 2 \g INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
\endpipeline \endpipeline
-- Multiple explicit transactions -- Multiple explicit transactions
\startpipeline \startpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
COMMIT \bind \g COMMIT \bind \sendpipeline
\endpipeline \endpipeline
-- COPY FROM STDIN -- COPY FROM STDIN
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\endpipeline \endpipeline
2 test2 2 test2
\. \.
-- COPY FROM STDIN with \flushrequest + \getresults -- COPY FROM STDIN with \flushrequest + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
3 test3 3 test3
@@ -85,8 +85,8 @@ COPY psql_pipeline FROM STDIN \bind \g
-- COPY FROM STDIN with \syncpipeline + \getresults -- COPY FROM STDIN with \syncpipeline + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
COPY psql_pipeline FROM STDIN \bind \g COPY psql_pipeline FROM STDIN \bind \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
4 test4 4 test4
@@ -95,22 +95,22 @@ COPY psql_pipeline FROM STDIN \bind \g
-- COPY TO STDOUT -- COPY TO STDOUT
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\endpipeline \endpipeline
-- COPY TO STDOUT with \flushrequest + \getresults -- COPY TO STDOUT with \flushrequest + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
\endpipeline \endpipeline
-- COPY TO STDOUT with \syncpipeline + \getresults -- COPY TO STDOUT with \syncpipeline + \getresults
\startpipeline \startpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
copy psql_pipeline TO STDOUT \bind \g copy psql_pipeline TO STDOUT \bind \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
\endpipeline \endpipeline
@@ -120,22 +120,22 @@ copy psql_pipeline TO STDOUT \bind \g
SELECT $1 \parse '' SELECT $1 \parse ''
SELECT $1, $2 \parse '' SELECT $1, $2 \parse ''
SELECT $2 \parse pipeline_1 SELECT $2 \parse pipeline_1
\bind_named '' 1 2 \g \bind_named '' 1 2 \sendpipeline
\bind_named pipeline_1 2 \g \bind_named pipeline_1 2 \sendpipeline
\endpipeline \endpipeline
-- \getresults displays all results preceding a \flushrequest. -- \getresults displays all results preceding a \flushrequest.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
\endpipeline \endpipeline
-- \getresults displays all results preceding a \syncpipeline. -- \getresults displays all results preceding a \syncpipeline.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\syncpipeline \syncpipeline
\getresults \getresults
\endpipeline \endpipeline
@@ -143,7 +143,7 @@ SELECT $1 \bind 2 \g
-- \getresults immediately returns if there is no result to fetch. -- \getresults immediately returns if there is no result to fetch.
\startpipeline \startpipeline
\getresults \getresults
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
\flushrequest \flushrequest
\endpipeline \endpipeline
@@ -151,42 +151,42 @@ SELECT $1 \bind 2 \g
-- \getresults only fetches results preceding a \flushrequest. -- \getresults only fetches results preceding a \flushrequest.
\startpipeline \startpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
\endpipeline \endpipeline
-- \getresults only fetches results preceding a \syncpipeline. -- \getresults only fetches results preceding a \syncpipeline.
\startpipeline \startpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\getresults \getresults
\endpipeline \endpipeline
-- Use pipeline with chunked results for both \getresults and \endpipeline. -- Use pipeline with chunked results for both \getresults and \endpipeline.
\startpipeline \startpipeline
\set FETCH_COUNT 10 \set FETCH_COUNT 10
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
\unset FETCH_COUNT \unset FETCH_COUNT
-- \getresults with specific number of requested results. -- \getresults with specific number of requested results.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
SELECT $1 \bind 3 \g SELECT $1 \bind 3 \sendpipeline
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
\syncpipeline \syncpipeline
\echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_SYNC_COUNT
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
\getresults 1 \getresults 1
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
SELECT $1 \bind 4 \g SELECT $1 \bind 4 \sendpipeline
\getresults 3 \getresults 3
\echo :PIPELINE_RESULT_COUNT \echo :PIPELINE_RESULT_COUNT
\endpipeline \endpipeline
@@ -195,7 +195,7 @@ SELECT $1 \bind 4 \g
\startpipeline \startpipeline
\syncpipeline \syncpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\flushrequest \flushrequest
\getresults 2 \getresults 2
\getresults 1 \getresults 1
@@ -203,9 +203,9 @@ SELECT $1 \bind 1 \g
-- \getresults 0 should get all the results. -- \getresults 0 should get all the results.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
SELECT $1 \bind 3 \g SELECT $1 \bind 3 \sendpipeline
\syncpipeline \syncpipeline
\getresults 0 \getresults 0
\endpipeline \endpipeline
@@ -221,36 +221,36 @@ SELECT $1 \bind 3 \g
-- pipeline usable. -- pipeline usable.
\startpipeline \startpipeline
SELECT 1; SELECT 1;
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
-- After an aborted pipeline, commands after a \syncpipeline should be -- After an aborted pipeline, commands after a \syncpipeline should be
-- displayed. -- displayed.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\syncpipeline \syncpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
-- For an incorrect number of parameters, the pipeline is aborted and -- For an incorrect number of parameters, the pipeline is aborted and
-- the following queries will not be executed. -- the following queries will not be executed.
\startpipeline \startpipeline
SELECT \bind 'val1' \g SELECT \bind 'val1' \sendpipeline
SELECT $1 \bind 'val1' \g SELECT $1 \bind 'val1' \sendpipeline
\endpipeline \endpipeline
-- An explicit transaction with an error needs to be rollbacked after -- An explicit transaction with an error needs to be rollbacked after
-- the pipeline. -- the pipeline.
\startpipeline \startpipeline
BEGIN \bind \g BEGIN \bind \sendpipeline
INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline
ROLLBACK \bind \g ROLLBACK \bind \sendpipeline
\endpipeline \endpipeline
ROLLBACK; ROLLBACK;
-- \watch sends a simple query, something not allowed within a pipeline. -- \watch sends a simple query, something not allowed within a pipeline.
\startpipeline \startpipeline
SELECT \bind \g SELECT \bind \sendpipeline
\watch 1 \watch 1
\endpipeline \endpipeline
@@ -258,7 +258,7 @@ SELECT \bind \g
-- and the pipeline should still be usable. -- and the pipeline should still be usable.
\startpipeline \startpipeline
SELECT $1 \bind 1 \gdesc SELECT $1 \bind 1 \gdesc
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
-- \gset is not allowed in a pipeline, pipeline should still be usable. -- \gset is not allowed in a pipeline, pipeline should still be usable.
@@ -267,54 +267,69 @@ SELECT $1 as i, $2 as j \parse ''
SELECT $1 as k, $2 as l \parse 'second' SELECT $1 as k, $2 as l \parse 'second'
\bind_named '' 1 2 \gset \bind_named '' 1 2 \gset
\bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j \bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j
\bind_named '' 1 2 \g \bind_named '' 1 2 \sendpipeline
\endpipeline \endpipeline
-- \gx is not allowed, pipeline should still be usable. -- \g and \gx are not allowed, pipeline should still be usable.
\startpipeline \startpipeline
SELECT $1 \bind 1 \gx
\reset
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \g
SELECT $1 \bind 1 \g (format=unaligned tuples_only=on)
SELECT $1 \bind 1 \gx
SELECT $1 \bind 1 \gx (format=unaligned tuples_only=on)
\reset
SELECT $1 \bind 1 \sendpipeline
\endpipeline \endpipeline
-- \gx warning should be emitted in an aborted pipeline, with -- \g and \gx warnings should be emitted in an aborted pipeline, with
-- pipeline still usable. -- pipeline still usable.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
SELECT $1 \bind 1 \g
SELECT $1 \bind 1 \gx SELECT $1 \bind 1 \gx
\endpipeline \endpipeline
-- \sendpipeline is not allowed outside of a pipeline
\sendpipeline
SELECT $1 \bind 1 \sendpipeline
\reset
-- \sendpipeline is not allowed if not preceded by \bind or \bind_named
\startpipeline
\sendpipeline
SELECT 1 \sendpipeline
\endpipeline
-- \gexec is not allowed, pipeline should still be usable. -- \gexec is not allowed, pipeline should still be usable.
\startpipeline \startpipeline
SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt'
\bind_named insert_stmt \gexec \bind_named insert_stmt \gexec
\bind_named insert_stmt \g \bind_named insert_stmt \sendpipeline
SELECT COUNT(*) FROM psql_pipeline \bind \g SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
-- After an error, pipeline is aborted and requires \syncpipeline to be -- After an error, pipeline is aborted and requires \syncpipeline to be
-- reusable. -- reusable.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
\flushrequest \flushrequest
\getresults \getresults
-- Pipeline is aborted. -- Pipeline is aborted.
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
-- Sync allows pipeline to recover. -- Sync allows pipeline to recover.
\syncpipeline \syncpipeline
\getresults \getresults
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\close a \close a
\flushrequest \flushrequest
\getresults \getresults
@@ -322,10 +337,10 @@ SELECT $1 \parse a
-- In an aborted pipeline, \getresults 1 aborts commands one at a time. -- In an aborted pipeline, \getresults 1 aborts commands one at a time.
\startpipeline \startpipeline
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
SELECT $1 \parse a SELECT $1 \parse a
\bind_named a 1 \g \bind_named a 1 \sendpipeline
\syncpipeline \syncpipeline
\getresults 1 \getresults 1
\getresults 1 \getresults 1
@@ -337,10 +352,10 @@ SELECT $1 \parse a
-- Test chunked results with an aborted pipeline. -- Test chunked results with an aborted pipeline.
\startpipeline \startpipeline
\set FETCH_COUNT 10 \set FETCH_COUNT 10
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\flushrequest \flushrequest
\getresults \getresults
SELECT $1 \bind \g SELECT $1 \bind \sendpipeline
\endpipeline \endpipeline
\unset FETCH_COUNT \unset FETCH_COUNT
@@ -356,7 +371,7 @@ select 1;
-- Error messages accumulate and are repeated. -- Error messages accumulate and are repeated.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
SELECT 1; SELECT 1;
SELECT 1; SELECT 1;
\endpipeline \endpipeline
@@ -371,66 +386,66 @@ SELECT 1;
-- commit the implicit transaction block. The first command after a -- commit the implicit transaction block. The first command after a
-- sync will not be seen as belonging to a pipeline. -- sync will not be seen as belonging to a pipeline.
\startpipeline \startpipeline
SET LOCAL statement_timeout='1h' \bind \g SET LOCAL statement_timeout='1h' \bind \sendpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
\syncpipeline \syncpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
SET LOCAL statement_timeout='2h' \bind \g SET LOCAL statement_timeout='2h' \bind \sendpipeline
SHOW statement_timeout \bind \g SHOW statement_timeout \bind \sendpipeline
\endpipeline \endpipeline
-- REINDEX CONCURRENTLY fails if not the first command in a pipeline. -- REINDEX CONCURRENTLY fails if not the first command in a pipeline.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
-- REINDEX CONCURRENTLY works if it is the first command in a pipeline. -- REINDEX CONCURRENTLY works if it is the first command in a pipeline.
\startpipeline \startpipeline
REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
-- Subtransactions are not allowed in a pipeline. -- Subtransactions are not allowed in a pipeline.
\startpipeline \startpipeline
SAVEPOINT a \bind \g SAVEPOINT a \bind \sendpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
ROLLBACK TO SAVEPOINT a \bind \g ROLLBACK TO SAVEPOINT a \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
-- LOCK fails as the first command in a pipeline, as not seen in an -- LOCK fails as the first command in a pipeline, as not seen in an
-- implicit transaction block. -- implicit transaction block.
\startpipeline \startpipeline
LOCK psql_pipeline \bind \g LOCK psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
-- LOCK succeeds as it is not the first command in a pipeline, -- LOCK succeeds as it is not the first command in a pipeline,
-- seen in an implicit transaction block. -- seen in an implicit transaction block.
\startpipeline \startpipeline
SELECT $1 \bind 1 \g SELECT $1 \bind 1 \sendpipeline
LOCK psql_pipeline \bind \g LOCK psql_pipeline \bind \sendpipeline
SELECT $1 \bind 2 \g SELECT $1 \bind 2 \sendpipeline
\endpipeline \endpipeline
-- VACUUM works as the first command in a pipeline. -- VACUUM works as the first command in a pipeline.
\startpipeline \startpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
-- VACUUM fails when not the first command in a pipeline. -- VACUUM fails when not the first command in a pipeline.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
-- VACUUM works after a \syncpipeline. -- VACUUM works after a \syncpipeline.
\startpipeline \startpipeline
SELECT 1 \bind \g SELECT 1 \bind \sendpipeline
\syncpipeline \syncpipeline
VACUUM psql_pipeline \bind \g VACUUM psql_pipeline \bind \sendpipeline
\endpipeline \endpipeline
-- Clean up -- Clean up