From b41f90e762bd64c72da5a0c50431b39d69062f22 Mon Sep 17 00:00:00 2001
From: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
Date: Wed, 20 Nov 2024 09:26:38 +0100
Subject: Reset query buffer on a backslash error

Some backslash command like can trigger an error before the query buffer
is processed, for example when a mandatory argument is missing.
However, the query_buffer won't be cleared and will be added to the next
command. For example:

SELECT 1 \parse
SELECT 2;

The parse command will fail as the named statement parameter is missing.
However, 'SELECT 1\n' will be kept in the query buffer and the next query
becomes 'SELECT 1\nSELECT 2;'

This patch fixes this behaviour by clearing the query buffer when
a backslash error is processed.
---
 src/bin/psql/command.c             |  2 ++
 src/test/regress/expected/psql.out | 17 ++++++++++++-----
 src/test/regress/sql/psql.sql      |  6 +++++-
 3 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index 1f3cbb11f7c..ca69912905f 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -266,6 +266,8 @@ HandleSlashCmds(PsqlScanState scan_state,
 		while ((arg = psql_scan_slash_option(scan_state,
 											 OT_WHOLE_LINE, NULL, false)))
 			free(arg);
+		/* and clear the query buffer */
+		resetPQExpBuffer(query_buf);
 	}
 
 	/* if there is a trailing \\, swallow it */
diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out
index 36dc31c16c4..3c51af09086 100644
--- a/src/test/regress/expected/psql.out
+++ b/src/test/regress/expected/psql.out
@@ -105,13 +105,17 @@ SELECT 1 \parse ''
 SELECT 2 \parse stmt1
 SELECT $1 \parse stmt2
 SELECT $1, $2 \parse stmt3
+-- An error due to missing argument should clear the query buffer
+SELECT 2 \parse
+\parse: missing required argument
+SELECT 3 \parse ''
 -- \bind_named (extended query protocol)
 \bind_named
 \bind_named: missing required argument
 \bind_named '' \g
  ?column? 
 ----------
-        1
+        3
 (1 row)
 
 \bind_named stmt1 \g
@@ -133,14 +137,17 @@ SELECT $1, $2 \parse stmt3
 (1 row)
 
 -- Repeated calls.  The second call generates an error, cleaning up the
--- statement name set by the first call.
+-- statement name and query buffer set by the first call.
 \bind_named stmt4
 \bind_named
 \bind_named: missing required argument
+-- Send mode and query buffer is reset, calling \g should send the previous query buffer
 \g
-ERROR:  there is no parameter $1
-LINE 1: SELECT $1, $2 
-               ^
+ ?column? 
+----------
+        3
+(1 row)
+
 -- Last \bind_named wins
 \bind_named stmt2 'foo' \bind_named stmt3 'foo2' 'bar2' \g
  ?column? | ?column? 
diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql
index c5021fc0b13..13342958f81 100644
--- a/src/test/regress/sql/psql.sql
+++ b/src/test/regress/sql/psql.sql
@@ -51,6 +51,9 @@ SELECT 1 \parse ''
 SELECT 2 \parse stmt1
 SELECT $1 \parse stmt2
 SELECT $1, $2 \parse stmt3
+-- An error due to missing argument should clear the query buffer
+SELECT 2 \parse
+SELECT 3 \parse ''
 
 -- \bind_named (extended query protocol)
 \bind_named
@@ -59,9 +62,10 @@ SELECT $1, $2 \parse stmt3
 \bind_named stmt2 'foo' \g
 \bind_named stmt3 'foo' 'bar' \g
 -- Repeated calls.  The second call generates an error, cleaning up the
--- statement name set by the first call.
+-- statement name and query buffer set by the first call.
 \bind_named stmt4
 \bind_named
+-- Send mode and query buffer is reset, calling \g should send the previous query buffer
 \g
 -- Last \bind_named wins
 \bind_named stmt2 'foo' \bind_named stmt3 'foo2' 'bar2' \g
-- 
2.39.5 (Apple Git-154)

