From 2ebe091c9fcc5cd35bbbc02ece90645539330ebd Mon Sep 17 00:00:00 2001 From: Anthonin Bonnefoy Date: Wed, 5 Mar 2025 14:55:33 +0100 Subject: psql: Allow ';' to add queries in an ongoing pipeline Currently, the only way to pipe queries in an ongoing pipeline is to leverage psql meta-commands to create extended queries such as \bind, \parse or \bind_named. This prevents using psql's pipeline on existing scripts as it would require to convert all queries to use those meta-commands. This patch modifies ';' behaviour within an active pipeline and send all queries as extended queries, allowing them to be piped in a pipeline. --- doc/src/sgml/ref/psql-ref.sgml | 21 +++++---- src/bin/psql/command.c | 7 +++ src/bin/psql/common.c | 10 +++- src/test/regress/expected/psql_pipeline.out | 52 +++++++++++++-------- src/test/regress/sql/psql_pipeline.sql | 24 ++++++---- 5 files changed, 77 insertions(+), 37 deletions(-) diff --git a/doc/src/sgml/ref/psql-ref.sgml b/doc/src/sgml/ref/psql-ref.sgml index cddf6e07531..2763486e268 100644 --- a/doc/src/sgml/ref/psql-ref.sgml +++ b/doc/src/sgml/ref/psql-ref.sgml @@ -3698,14 +3698,19 @@ testdb=> \setenv LESS -imx4F - Pipeline mode requires the use of the extended query protocol. All - queries need to be sent using the meta-commands - \bind, \bind_named, - \close or \parse. While a - pipeline is ongoing, \sendpipeline will append the - current query buffer to the pipeline. Other meta-commands like - \g, \gx or \gdesc - are not allowed in pipeline mode. + Pipeline mode requires the use of the extended query protocol. Queries + can be sent using the meta-commands \bind, + \bind_named, \close or + \parse. While a pipeline is ongoing, + \sendpipeline will append the current query + buffer to the pipeline. Other meta-commands like \g, + \gx or \gdesc are not allowed + in pipeline mode. + + + + Queries can also be sent using ;. While a pipeline is + ongoing, they will automatically be sent using extended query protocol. diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c index 7670c20b29e..3e7eb086367 100644 --- a/src/bin/psql/command.c +++ b/src/bin/psql/command.c @@ -3282,6 +3282,13 @@ exec_command_watch(PsqlScanState scan_state, bool active_branch, int iter = 0; int min_rows = 0; + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + pg_log_error("\\watch not allowed in pipeline mode"); + clean_extended_state(); + success = false; + } + /* * Parse arguments. We allow either an unlabeled interval or * "name=value", where name is from the set ('i', 'interval', 'c', diff --git a/src/bin/psql/common.c b/src/bin/psql/common.c index ed340a466f9..5249336bcf2 100644 --- a/src/bin/psql/common.c +++ b/src/bin/psql/common.c @@ -1668,7 +1668,15 @@ ExecQueryAndProcessResults(const char *query, } break; case PSQL_SEND_QUERY: - success = PQsendQuery(pset.db, query); + if (PQpipelineStatus(pset.db) != PQ_PIPELINE_OFF) + { + success = PQsendQueryParams(pset.db, query, + 0, NULL, NULL, NULL, NULL, 0); + if (success) + pset.piped_commands++; + } + else + success = PQsendQuery(pset.db, query); break; } diff --git a/src/test/regress/expected/psql_pipeline.out b/src/test/regress/expected/psql_pipeline.out index 53f2edfd986..f05429b36ac 100644 --- a/src/test/regress/expected/psql_pipeline.out +++ b/src/test/regress/expected/psql_pipeline.out @@ -387,24 +387,33 @@ SELECT $1 \bind 3 \sendpipeline (1 row) \endpipeline +-- Queries can be pipelined ';'. They will be sent using extended protocol. +\startpipeline +SELECT 1; +SELECT $1 \bind 'val1' \sendpipeline +SELECT 2; +\endpipeline + ?column? +---------- + 1 +(1 row) + + ?column? +---------- + val1 +(1 row) + + ?column? +---------- + 2 +(1 row) + -- -- Pipeline errors -- -- \endpipeline outside of pipeline should fail \endpipeline cannot send pipeline when not in pipeline mode --- Query using simple protocol should not be sent and should leave the --- pipeline usable. -\startpipeline -SELECT 1; -PQsendQuery not allowed in pipeline mode -SELECT $1 \bind 'val1' \sendpipeline -\endpipeline - ?column? ----------- - val1 -(1 row) - -- After an aborted pipeline, commands after a \syncpipeline should be -- displayed. \startpipeline @@ -425,6 +434,12 @@ SELECT \bind 'val1' \sendpipeline SELECT $1 \bind 'val1' \sendpipeline \endpipeline ERROR: bind message supplies 1 parameters, but prepared statement "" requires 0 +-- Using ';' with a parameter will trigger an incorrect parameter errors. +\startpipeline +SELECT $1; +SELECT 1; +\endpipeline +ERROR: bind message supplies 0 parameters, but prepared statement "" requires 1 -- An explicit transaction with an error needs to be rollbacked after -- the pipeline. \startpipeline @@ -439,8 +454,7 @@ ROLLBACK; \startpipeline SELECT \bind \sendpipeline \watch 1 -PQsendQuery not allowed in pipeline mode - +\watch not allowed in pipeline mode \endpipeline -- (1 row) @@ -619,11 +633,11 @@ select 1; -- Error messages accumulate and are repeated. \startpipeline SELECT 1 \bind \sendpipeline -SELECT 1; -PQsendQuery not allowed in pipeline mode -SELECT 1; -PQsendQuery not allowed in pipeline mode -PQsendQuery not allowed in pipeline mode +\gdesc +synchronous command execution functions are not allowed in pipeline mode +\gdesc +synchronous command execution functions are not allowed in pipeline mode +synchronous command execution functions are not allowed in pipeline mode \endpipeline ?column? ---------- diff --git a/src/test/regress/sql/psql_pipeline.sql b/src/test/regress/sql/psql_pipeline.sql index 256081dfd5f..76c0ece01af 100644 --- a/src/test/regress/sql/psql_pipeline.sql +++ b/src/test/regress/sql/psql_pipeline.sql @@ -210,6 +210,13 @@ SELECT $1 \bind 3 \sendpipeline \getresults 0 \endpipeline +-- Queries can be pipelined ';'. They will be sent using extended protocol. +\startpipeline +SELECT 1; +SELECT $1 \bind 'val1' \sendpipeline +SELECT 2; +\endpipeline + -- -- Pipeline errors -- @@ -217,13 +224,6 @@ SELECT $1 \bind 3 \sendpipeline -- \endpipeline outside of pipeline should fail \endpipeline --- Query using simple protocol should not be sent and should leave the --- pipeline usable. -\startpipeline -SELECT 1; -SELECT $1 \bind 'val1' \sendpipeline -\endpipeline - -- After an aborted pipeline, commands after a \syncpipeline should be -- displayed. \startpipeline @@ -239,6 +239,12 @@ SELECT \bind 'val1' \sendpipeline SELECT $1 \bind 'val1' \sendpipeline \endpipeline +-- Using ';' with a parameter will trigger an incorrect parameter errors. +\startpipeline +SELECT $1; +SELECT 1; +\endpipeline + -- An explicit transaction with an error needs to be rollbacked after -- the pipeline. \startpipeline @@ -375,8 +381,8 @@ select 1; -- Error messages accumulate and are repeated. \startpipeline SELECT 1 \bind \sendpipeline -SELECT 1; -SELECT 1; +\gdesc +\gdesc \endpipeline -- -- 2.39.5 (Apple Git-154)