diff options
-rw-r--r-- | doc/src/sgml/ref/psql-ref.sgml | 11 | ||||
-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 | ||||
-rw-r--r-- | src/test/regress/expected/psql.out | 1 | ||||
-rw-r--r-- | src/test/regress/expected/psql_pipeline.out | 237 | ||||
-rw-r--r-- | src/test/regress/sql/psql.sql | 1 | ||||
-rw-r--r-- | src/test/regress/sql/psql_pipeline.sql | 231 |
8 files changed, 305 insertions, 225 deletions
diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index cedccc14129..cddf6e07531 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -3677,6 +3677,7 @@ testdb=> <userinput>\setenv LESS -imx4F</userinput> <varlistentry id="app-psql-meta-command-pipeline"> <term><literal>\startpipeline</literal></term> + <term><literal>\sendpipeline</literal></term> <term><literal>\syncpipeline</literal></term> <term><literal>\endpipeline</literal></term> <term><literal>\flushrequest</literal></term> @@ -3701,10 +3702,10 @@ testdb=> <userinput>\setenv LESS -imx4F</userinput> queries need to be sent using the meta-commands <literal>\bind</literal>, <literal>\bind_named</literal>, <literal>\close</literal> or <literal>\parse</literal>. While a - pipeline is ongoing, <literal>\g</literal> will append the current - query buffer to the pipeline. Other meta-commands like - <literal>\gx</literal> or <literal>\gdesc</literal> are not allowed - in pipeline mode. + pipeline is ongoing, <literal>\sendpipeline</literal> will append the + current query buffer to the pipeline. Other meta-commands like + <literal>\g</literal>, <literal>\gx</literal> or <literal>\gdesc</literal> + are not allowed in pipeline mode. </para> <para> @@ -3738,7 +3739,7 @@ testdb=> <userinput>\setenv LESS -imx4F</userinput> Example: <programlisting> \startpipeline -SELECT 1 \bind \g +SELECT 1 \bind \sendpipeline \flushrequest \getresults \endpipeline 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", diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 6543e90de75..8687ffe2750 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -4706,6 +4706,7 @@ invalid command \lo \q \reset \s arg1 + \sendpipeline \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \setenv arg1 arg2 \sf whole_line diff --git a/src/test/regress/expected/psql_pipeline.out b/src/test/regress/expected/psql_pipeline.out index 3df2415a840..68e3c19ea05 100644 --- a/src/test/regress/expected/psql_pipeline.out +++ b/src/test/regress/expected/psql_pipeline.out @@ -4,7 +4,7 @@ CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); -- Single query \startpipeline -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline ?column? ---------- @@ -13,9 +13,9 @@ SELECT $1 \bind 'val1' \g -- Multiple queries \startpipeline -SELECT $1 \bind 'val1' \g -SELECT $1, $2 \bind 'val2' 'val3' \g -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1 \bind 'val1' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \endpipeline ?column? ---------- @@ -35,10 +35,10 @@ SELECT $1, $2 \bind 'val2' 'val3' \g -- Test \flush \startpipeline \flush -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \flush -SELECT $1, $2 \bind 'val2' 'val3' \g -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \endpipeline ?column? ---------- @@ -63,12 +63,12 @@ SELECT $1, $2 \bind 'val2' 'val3' \g 0 \echo :PIPELINE_RESULT_COUNT 0 -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \syncpipeline \syncpipeline -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \syncpipeline -SELECT $1, $2 \bind 'val4' 'val5' \g +SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline \echo :PIPELINE_COMMAND_COUNT 1 \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 \startpipeline -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline ?column? ---------- @@ -103,24 +103,24 @@ SELECT $1 \bind 'val1' \g -- Convert an implicit transaction block to an explicit transaction block. \startpipeline -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 2 \g -ROLLBACK \bind \g +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline +ROLLBACK \bind \sendpipeline \endpipeline -- Multiple explicit transactions \startpipeline -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -ROLLBACK \bind \g -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -COMMIT \bind \g +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +COMMIT \bind \sendpipeline \endpipeline -- COPY FROM STDIN \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \endpipeline ?column? ---------- @@ -129,8 +129,8 @@ COPY psql_pipeline FROM STDIN \bind \g -- COPY FROM STDIN with \flushrequest + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \flushrequest \getresults ?column? @@ -142,8 +142,8 @@ message type 0x5a arrived from server while idle \endpipeline -- COPY FROM STDIN with \syncpipeline + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \syncpipeline \getresults ?column? @@ -154,8 +154,8 @@ COPY psql_pipeline FROM STDIN \bind \g \endpipeline -- COPY TO STDOUT \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \endpipeline ?column? ---------- @@ -168,8 +168,8 @@ copy psql_pipeline TO STDOUT \bind \g 4 test4 -- COPY TO STDOUT with \flushrequest + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \flushrequest \getresults ?column? @@ -184,8 +184,8 @@ copy psql_pipeline TO STDOUT \bind \g \endpipeline -- COPY TO STDOUT with \syncpipeline + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \syncpipeline \getresults ?column? @@ -203,14 +203,14 @@ copy psql_pipeline TO STDOUT \bind \g SELECT $1 \parse '' SELECT $1, $2 \parse '' SELECT $2 \parse pipeline_1 -\bind_named '' 1 2 \g -\bind_named pipeline_1 2 \g +\bind_named '' 1 2 \sendpipeline +\bind_named pipeline_1 2 \sendpipeline \endpipeline ERROR: could not determine data type of parameter $1 -- \getresults displays all results preceding a \flushrequest. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline \flushrequest \getresults ?column? @@ -226,8 +226,8 @@ SELECT $1 \bind 2 \g \endpipeline -- \getresults displays all results preceding a \syncpipeline. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline \syncpipeline \getresults ?column? @@ -245,7 +245,7 @@ SELECT $1 \bind 2 \g \startpipeline \getresults No pending results to get -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults No pending results to get \flushrequest @@ -259,9 +259,9 @@ No pending results to get No pending results to get -- \getresults only fetches results preceding a \flushrequest. \startpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \flushrequest -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults ?column? ---------- @@ -276,9 +276,9 @@ SELECT $1 \bind 2 \g -- \getresults only fetches results preceding a \syncpipeline. \startpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \syncpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults ?column? ---------- @@ -294,7 +294,7 @@ SELECT $1 \bind 2 \g -- Use pipeline with chunked results for both \getresults and \endpipeline. \startpipeline \set FETCH_COUNT 10 -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \flushrequest \getresults ?column? @@ -302,7 +302,7 @@ SELECT $1 \bind 2 \g 2 (1 row) -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \endpipeline ?column? ---------- @@ -312,9 +312,9 @@ SELECT $1 \bind 2 \g \unset FETCH_COUNT -- \getresults with specific number of requested results. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g -SELECT $1 \bind 3 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline \echo :PIPELINE_SYNC_COUNT 0 \syncpipeline @@ -330,7 +330,7 @@ SELECT $1 \bind 3 \g \echo :PIPELINE_RESULT_COUNT 2 -SELECT $1 \bind 4 \g +SELECT $1 \bind 4 \sendpipeline \getresults 3 ?column? ---------- @@ -354,7 +354,7 @@ SELECT $1 \bind 4 \g \startpipeline \syncpipeline \syncpipeline -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \flushrequest \getresults 2 \getresults 1 @@ -366,9 +366,9 @@ SELECT $1 \bind 1 \g \endpipeline -- \getresults 0 should get all the results. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g -SELECT $1 \bind 3 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline \syncpipeline \getresults 0 ?column? @@ -398,7 +398,7 @@ cannot send pipeline when not in pipeline mode \startpipeline SELECT 1; PQsendQuery not allowed in pipeline mode -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline ?column? ---------- @@ -408,9 +408,9 @@ SELECT $1 \bind 'val1' \g -- After an aborted pipeline, commands after a \syncpipeline should be -- displayed. \startpipeline -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \syncpipeline -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \endpipeline ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 ?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 -- the following queries will not be executed. \startpipeline -SELECT \bind 'val1' \g -SELECT $1 \bind 'val1' \g +SELECT \bind 'val1' \sendpipeline +SELECT $1 \bind 'val1' \sendpipeline \endpipeline ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0 -- An explicit transaction with an error needs to be rollbacked after -- the pipeline. \startpipeline -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -ROLLBACK \bind \g +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline \endpipeline ERROR: duplicate key value violates unique constraint "psql_pipeline_pkey" DETAIL: Key (a)=(1) already exists. ROLLBACK; -- \watch sends a simple query, something not allowed within a pipeline. \startpipeline -SELECT \bind \g +SELECT \bind \sendpipeline \watch 1 PQsendQuery not allowed in pipeline mode @@ -450,7 +450,7 @@ PQsendQuery not allowed in pipeline mode \startpipeline SELECT $1 \bind 1 \gdesc synchronous command execution functions are not allowed in pipeline mode -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \endpipeline ?column? ---------- @@ -465,42 +465,63 @@ SELECT $1 as k, $2 as l \parse 'second' \gset not allowed in pipeline mode \bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j \gset not allowed in pipeline mode -\bind_named '' 1 2 \g +\bind_named '' 1 2 \sendpipeline \endpipeline i | j ---+--- 1 | 2 (1 row) --- \gx is not allowed, pipeline should still be usable. +-- \g and \gx are not allowed, pipeline should still be usable. \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 \gx not allowed in pipeline mode +SELECT $1 \bind 1 \gx (format=unaligned tuples_only=on) +\gx not allowed in pipeline mode \reset -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \endpipeline ?column? ---------- 1 (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. \startpipeline -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \flushrequest \getresults 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 \gx not allowed in pipeline mode \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. \startpipeline SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' \bind_named insert_stmt \gexec \gexec not allowed in pipeline mode -\bind_named insert_stmt \g -SELECT COUNT(*) FROM psql_pipeline \bind \g +\bind_named insert_stmt \sendpipeline +SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline \endpipeline ?column? ------------------------------------------------------------ @@ -515,26 +536,26 @@ SELECT COUNT(*) FROM psql_pipeline \bind \g -- After an error, pipeline is aborted and requires \syncpipeline to be -- reusable. \startpipeline -SELECT $1 \bind \g -SELECT $1 \bind 1 \g +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a \flushrequest \getresults ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 -- Pipeline is aborted. -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a -- Sync allows pipeline to recover. \syncpipeline \getresults Pipeline aborted, command did not run -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a \flushrequest \getresults @@ -551,10 +572,10 @@ SELECT $1 \parse a \endpipeline -- In an aborted pipeline, \getresults 1 aborts commands one at a time. \startpipeline -SELECT $1 \bind \g -SELECT $1 \bind 1 \g +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \syncpipeline \getresults 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. \startpipeline \set FETCH_COUNT 10 -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \flushrequest \getresults ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \endpipeline fetching results in chunked mode failed Pipeline aborted, command did not run @@ -595,7 +616,7 @@ select 1; -- Error messages accumulate and are repeated. \startpipeline -SELECT 1 \bind \g +SELECT 1 \bind \sendpipeline SELECT 1; PQsendQuery not allowed in pipeline mode SELECT 1; @@ -616,12 +637,12 @@ PQsendQuery not allowed in pipeline mode -- commit the implicit transaction block. The first command after a -- sync will not be seen as belonging to a pipeline. \startpipeline -SET LOCAL statement_timeout='1h' \bind \g -SHOW statement_timeout \bind \g +SET LOCAL statement_timeout='1h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline \syncpipeline -SHOW statement_timeout \bind \g -SET LOCAL statement_timeout='2h' \bind \g -SHOW statement_timeout \bind \g +SHOW statement_timeout \bind \sendpipeline +SET LOCAL statement_timeout='2h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline \endpipeline WARNING: SET LOCAL can only be used in transaction blocks 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. \startpipeline -SELECT $1 \bind 1 \g -REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline ?column? ---------- @@ -653,8 +674,8 @@ SELECT $1 \bind 2 \g ERROR: REINDEX CONCURRENTLY cannot run inside a transaction block -- REINDEX CONCURRENTLY works if it is the first command in a pipeline. \startpipeline -REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g -SELECT $1 \bind 2 \g +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline ?column? ---------- @@ -663,25 +684,25 @@ SELECT $1 \bind 2 \g -- Subtransactions are not allowed in a pipeline. \startpipeline -SAVEPOINT a \bind \g -SELECT $1 \bind 1 \g -ROLLBACK TO SAVEPOINT a \bind \g -SELECT $1 \bind 2 \g +SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +ROLLBACK TO SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline ERROR: SAVEPOINT can only be used in transaction blocks -- LOCK fails as the first command in a pipeline, as not seen in an -- implicit transaction block. \startpipeline -LOCK psql_pipeline \bind \g -SELECT $1 \bind 2 \g +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline ERROR: LOCK TABLE can only be used in transaction blocks -- LOCK succeeds as it is not the first command in a pipeline, -- seen in an implicit transaction block. \startpipeline -SELECT $1 \bind 1 \g -LOCK psql_pipeline \bind \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline ?column? ---------- @@ -695,12 +716,12 @@ SELECT $1 \bind 2 \g -- VACUUM works as the first command in a pipeline. \startpipeline -VACUUM psql_pipeline \bind \g +VACUUM psql_pipeline \bind \sendpipeline \endpipeline -- VACUUM fails when not the first command in a pipeline. \startpipeline -SELECT 1 \bind \g -VACUUM psql_pipeline \bind \g +SELECT 1 \bind \sendpipeline +VACUUM psql_pipeline \bind \sendpipeline \endpipeline ?column? ---------- @@ -710,9 +731,9 @@ VACUUM psql_pipeline \bind \g ERROR: VACUUM cannot run inside a transaction block -- VACUUM works after a \syncpipeline. \startpipeline -SELECT 1 \bind \g +SELECT 1 \bind \sendpipeline \syncpipeline -VACUUM psql_pipeline \bind \g +VACUUM psql_pipeline \bind \sendpipeline \endpipeline ?column? ---------- diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index 97d1be3aac3..1a8a83462f0 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -1074,6 +1074,7 @@ select \if false \\ (bogus \else \\ 42 \endif \\ forty_two; \q \reset \s arg1 + \sendpipeline \set arg1 arg2 arg3 arg4 arg5 arg6 arg7 \setenv arg1 arg2 \sf whole_line diff --git a/src/test/regress/sql/psql_pipeline.sql b/src/test/regress/sql/psql_pipeline.sql index 6517ebb71f8..e4d7e614af3 100644 --- a/src/test/regress/sql/psql_pipeline.sql +++ b/src/test/regress/sql/psql_pipeline.sql @@ -6,23 +6,23 @@ CREATE TABLE psql_pipeline(a INTEGER PRIMARY KEY, s TEXT); -- Single query \startpipeline -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline -- Multiple queries \startpipeline -SELECT $1 \bind 'val1' \g -SELECT $1, $2 \bind 'val2' 'val3' \g -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1 \bind 'val1' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \endpipeline -- Test \flush \startpipeline \flush -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \flush -SELECT $1, $2 \bind 'val2' 'val3' \g -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \endpipeline -- Send multiple syncs @@ -30,12 +30,12 @@ SELECT $1, $2 \bind 'val2' 'val3' \g \echo :PIPELINE_COMMAND_COUNT \echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_RESULT_COUNT -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \syncpipeline \syncpipeline -SELECT $1, $2 \bind 'val2' 'val3' \g +SELECT $1, $2 \bind 'val2' 'val3' \sendpipeline \syncpipeline -SELECT $1, $2 \bind 'val4' 'val5' \g +SELECT $1, $2 \bind 'val4' 'val5' \sendpipeline \echo :PIPELINE_COMMAND_COUNT \echo :PIPELINE_SYNC_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 \startpipeline -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline -- Convert an implicit transaction block to an explicit transaction block. \startpipeline -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 2 \g -ROLLBACK \bind \g +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 2 \sendpipeline +ROLLBACK \bind \sendpipeline \endpipeline -- Multiple explicit transactions \startpipeline -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -ROLLBACK \bind \g -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -COMMIT \bind \g +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +COMMIT \bind \sendpipeline \endpipeline -- COPY FROM STDIN \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \endpipeline 2 test2 \. -- COPY FROM STDIN with \flushrequest + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \flushrequest \getresults 3 test3 @@ -85,8 +85,8 @@ COPY psql_pipeline FROM STDIN \bind \g -- COPY FROM STDIN with \syncpipeline + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -COPY psql_pipeline FROM STDIN \bind \g +SELECT $1 \bind 'val1' \sendpipeline +COPY psql_pipeline FROM STDIN \bind \sendpipeline \syncpipeline \getresults 4 test4 @@ -95,22 +95,22 @@ COPY psql_pipeline FROM STDIN \bind \g -- COPY TO STDOUT \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \endpipeline -- COPY TO STDOUT with \flushrequest + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \flushrequest \getresults \endpipeline -- COPY TO STDOUT with \syncpipeline + \getresults \startpipeline -SELECT $1 \bind 'val1' \g -copy psql_pipeline TO STDOUT \bind \g +SELECT $1 \bind 'val1' \sendpipeline +copy psql_pipeline TO STDOUT \bind \sendpipeline \syncpipeline \getresults \endpipeline @@ -120,22 +120,22 @@ copy psql_pipeline TO STDOUT \bind \g SELECT $1 \parse '' SELECT $1, $2 \parse '' SELECT $2 \parse pipeline_1 -\bind_named '' 1 2 \g -\bind_named pipeline_1 2 \g +\bind_named '' 1 2 \sendpipeline +\bind_named pipeline_1 2 \sendpipeline \endpipeline -- \getresults displays all results preceding a \flushrequest. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline \flushrequest \getresults \endpipeline -- \getresults displays all results preceding a \syncpipeline. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline \syncpipeline \getresults \endpipeline @@ -143,7 +143,7 @@ SELECT $1 \bind 2 \g -- \getresults immediately returns if there is no result to fetch. \startpipeline \getresults -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults \flushrequest \endpipeline @@ -151,42 +151,42 @@ SELECT $1 \bind 2 \g -- \getresults only fetches results preceding a \flushrequest. \startpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \flushrequest -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults \endpipeline -- \getresults only fetches results preceding a \syncpipeline. \startpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \syncpipeline -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \getresults \endpipeline -- Use pipeline with chunked results for both \getresults and \endpipeline. \startpipeline \set FETCH_COUNT 10 -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \flushrequest \getresults -SELECT $1 \bind 2 \g +SELECT $1 \bind 2 \sendpipeline \endpipeline \unset FETCH_COUNT -- \getresults with specific number of requested results. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g -SELECT $1 \bind 3 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline \echo :PIPELINE_SYNC_COUNT \syncpipeline \echo :PIPELINE_SYNC_COUNT \echo :PIPELINE_RESULT_COUNT \getresults 1 \echo :PIPELINE_RESULT_COUNT -SELECT $1 \bind 4 \g +SELECT $1 \bind 4 \sendpipeline \getresults 3 \echo :PIPELINE_RESULT_COUNT \endpipeline @@ -195,7 +195,7 @@ SELECT $1 \bind 4 \g \startpipeline \syncpipeline \syncpipeline -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \flushrequest \getresults 2 \getresults 1 @@ -203,9 +203,9 @@ SELECT $1 \bind 1 \g -- \getresults 0 should get all the results. \startpipeline -SELECT $1 \bind 1 \g -SELECT $1 \bind 2 \g -SELECT $1 \bind 3 \g +SELECT $1 \bind 1 \sendpipeline +SELECT $1 \bind 2 \sendpipeline +SELECT $1 \bind 3 \sendpipeline \syncpipeline \getresults 0 \endpipeline @@ -221,36 +221,36 @@ SELECT $1 \bind 3 \g -- pipeline usable. \startpipeline SELECT 1; -SELECT $1 \bind 'val1' \g +SELECT $1 \bind 'val1' \sendpipeline \endpipeline -- After an aborted pipeline, commands after a \syncpipeline should be -- displayed. \startpipeline -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \syncpipeline -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \endpipeline -- For an incorrect number of parameters, the pipeline is aborted and -- the following queries will not be executed. \startpipeline -SELECT \bind 'val1' \g -SELECT $1 \bind 'val1' \g +SELECT \bind 'val1' \sendpipeline +SELECT $1 \bind 'val1' \sendpipeline \endpipeline -- An explicit transaction with an error needs to be rollbacked after -- the pipeline. \startpipeline -BEGIN \bind \g -INSERT INTO psql_pipeline VALUES ($1) \bind 1 \g -ROLLBACK \bind \g +BEGIN \bind \sendpipeline +INSERT INTO psql_pipeline VALUES ($1) \bind 1 \sendpipeline +ROLLBACK \bind \sendpipeline \endpipeline ROLLBACK; -- \watch sends a simple query, something not allowed within a pipeline. \startpipeline -SELECT \bind \g +SELECT \bind \sendpipeline \watch 1 \endpipeline @@ -258,7 +258,7 @@ SELECT \bind \g -- and the pipeline should still be usable. \startpipeline SELECT $1 \bind 1 \gdesc -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline \endpipeline -- \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' \bind_named '' 1 2 \gset \bind_named second 1 2 \gset pref02_ \echo :pref02_i :pref02_j -\bind_named '' 1 2 \g +\bind_named '' 1 2 \sendpipeline \endpipeline --- \gx is not allowed, pipeline should still be usable. +-- \g and \gx are not allowed, pipeline should still be usable. \startpipeline +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 \g +SELECT $1 \bind 1 \sendpipeline \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. \startpipeline -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \flushrequest \getresults +SELECT $1 \bind 1 \g SELECT $1 \bind 1 \gx \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. \startpipeline SELECT 'INSERT INTO psql_pipeline(a) SELECT generate_series(1, 10)' \parse 'insert_stmt' \bind_named insert_stmt \gexec -\bind_named insert_stmt \g -SELECT COUNT(*) FROM psql_pipeline \bind \g +\bind_named insert_stmt \sendpipeline +SELECT COUNT(*) FROM psql_pipeline \bind \sendpipeline \endpipeline -- After an error, pipeline is aborted and requires \syncpipeline to be -- reusable. \startpipeline -SELECT $1 \bind \g -SELECT $1 \bind 1 \g +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a \flushrequest \getresults -- Pipeline is aborted. -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a -- Sync allows pipeline to recover. \syncpipeline \getresults -SELECT $1 \bind 1 \g +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \close a \flushrequest \getresults @@ -322,10 +337,10 @@ SELECT $1 \parse a -- In an aborted pipeline, \getresults 1 aborts commands one at a time. \startpipeline -SELECT $1 \bind \g -SELECT $1 \bind 1 \g +SELECT $1 \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline SELECT $1 \parse a -\bind_named a 1 \g +\bind_named a 1 \sendpipeline \syncpipeline \getresults 1 \getresults 1 @@ -337,10 +352,10 @@ SELECT $1 \parse a -- Test chunked results with an aborted pipeline. \startpipeline \set FETCH_COUNT 10 -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \flushrequest \getresults -SELECT $1 \bind \g +SELECT $1 \bind \sendpipeline \endpipeline \unset FETCH_COUNT @@ -356,7 +371,7 @@ select 1; -- Error messages accumulate and are repeated. \startpipeline -SELECT 1 \bind \g +SELECT 1 \bind \sendpipeline SELECT 1; SELECT 1; \endpipeline @@ -371,66 +386,66 @@ SELECT 1; -- commit the implicit transaction block. The first command after a -- sync will not be seen as belonging to a pipeline. \startpipeline -SET LOCAL statement_timeout='1h' \bind \g -SHOW statement_timeout \bind \g +SET LOCAL statement_timeout='1h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline \syncpipeline -SHOW statement_timeout \bind \g -SET LOCAL statement_timeout='2h' \bind \g -SHOW statement_timeout \bind \g +SHOW statement_timeout \bind \sendpipeline +SET LOCAL statement_timeout='2h' \bind \sendpipeline +SHOW statement_timeout \bind \sendpipeline \endpipeline -- REINDEX CONCURRENTLY fails if not the first command in a pipeline. \startpipeline -SELECT $1 \bind 1 \g -REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline -- REINDEX CONCURRENTLY works if it is the first command in a pipeline. \startpipeline -REINDEX TABLE CONCURRENTLY psql_pipeline \bind \g -SELECT $1 \bind 2 \g +REINDEX TABLE CONCURRENTLY psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline -- Subtransactions are not allowed in a pipeline. \startpipeline -SAVEPOINT a \bind \g -SELECT $1 \bind 1 \g -ROLLBACK TO SAVEPOINT a \bind \g -SELECT $1 \bind 2 \g +SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 1 \sendpipeline +ROLLBACK TO SAVEPOINT a \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline -- LOCK fails as the first command in a pipeline, as not seen in an -- implicit transaction block. \startpipeline -LOCK psql_pipeline \bind \g -SELECT $1 \bind 2 \g +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline -- LOCK succeeds as it is not the first command in a pipeline, -- seen in an implicit transaction block. \startpipeline -SELECT $1 \bind 1 \g -LOCK psql_pipeline \bind \g -SELECT $1 \bind 2 \g +SELECT $1 \bind 1 \sendpipeline +LOCK psql_pipeline \bind \sendpipeline +SELECT $1 \bind 2 \sendpipeline \endpipeline -- VACUUM works as the first command in a pipeline. \startpipeline -VACUUM psql_pipeline \bind \g +VACUUM psql_pipeline \bind \sendpipeline \endpipeline -- VACUUM fails when not the first command in a pipeline. \startpipeline -SELECT 1 \bind \g -VACUUM psql_pipeline \bind \g +SELECT 1 \bind \sendpipeline +VACUUM psql_pipeline \bind \sendpipeline \endpipeline -- VACUUM works after a \syncpipeline. \startpipeline -SELECT 1 \bind \g +SELECT 1 \bind \sendpipeline \syncpipeline -VACUUM psql_pipeline \bind \g +VACUUM psql_pipeline \bind \sendpipeline \endpipeline -- Clean up |