From a155adf6c1e6a6c31cf4146ce53827180247f384 Mon Sep 17 00:00:00 2001
From: Peifeng Qiu <pgsql@qiupf.dev>
Date: Thu, 29 Dec 2022 11:37:19 +0900
Subject: [PATCH] psql: stop at error immediately during \copy

---
 src/bin/psql/copy.c                 |  7 +++++++
 src/interfaces/libpq/fe-protocol3.c | 13 +++++++++++++
 2 files changed, 20 insertions(+)

diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index 0f66ebc2ed..1d285312c2 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -580,6 +580,7 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
 		bool		copydone = false;
 		int			buflen;
 		bool		at_line_begin = true;
+		char	   *err;
 
 		/*
 		 * In text mode, we have to read the input one line at a time, so that
@@ -660,6 +661,12 @@ handleCopyIn(PGconn *conn, FILE *copystream, bool isbinary, PGresult **res)
 					OK = false;
 					break;
 				}
+				err = PQerrorMessage(conn);
+				if (err && *err)
+				{
+					/* We got error from server backend. Stop processing. */
+					break;
+				}
 
 				buflen = 0;
 			}
diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c
index 364bad2b88..b50ce7da2e 100644
--- a/src/interfaces/libpq/fe-protocol3.c
+++ b/src/interfaces/libpq/fe-protocol3.c
@@ -150,6 +150,19 @@ pqParseInput3(PGconn *conn)
 			if (pqGetErrorNotice3(conn, false))
 				return;
 		}
+		else if (conn->asyncStatus == PGASYNC_COPY_IN)
+		{
+			/*
+			 * Process and save error message during COPY. Client can check
+			 * this error via PQerrorMessage.
+			 */
+			if (id == 'E')
+			{
+				if (pqGetErrorNotice3(conn, true))
+					return;
+				break;
+			}
+		}
 		else if (conn->asyncStatus != PGASYNC_BUSY)
 		{
 			/* If not IDLE state, just wait ... */
-- 
2.39.0

