From af9c10274e73a4e7a5c50f8e13ae4083689f4664 Mon Sep 17 00:00:00 2001
From: Shinya Kato <shinya11.kato@gmail.com>
Date: Tue, 20 Jan 2026 11:02:49 +0900
Subject: [PATCH v5 1/2] Improve the error message in COPY with HEADER option.

The error message reported for invalid values of the HEADER option in COPY
command previously used the term "non-negative integer", which is
discouraged by the Error Message Style Guide because it is ambiguous about
whether zero is allowed.

This commit improves the error message by replacing "non-negative integer"
there with "an integer value greater than or equal to zero" to make
the accepted values explicit.

Author: Shinya Kato <shinya11.kato@gmail.com>
Reviewed-by: Fujii Masao <masao.fujii@gmail.com>
Discussion: https://postgr.es/m/CAHGQGwE86PcuPZbP=aurmW7Oo=eycF10gxjErWq4NmY-5TTX4Q@mail.gmail.com
---
 src/backend/commands/copy.c         | 13 +++++++------
 src/test/regress/expected/copy.out  |  2 +-
 src/test/regress/expected/copy2.out |  2 +-
 3 files changed, 9 insertions(+), 8 deletions(-)

diff --git a/src/backend/commands/copy.c b/src/backend/commands/copy.c
index 9c51384ab92..a69c2419704 100644
--- a/src/backend/commands/copy.c
+++ b/src/backend/commands/copy.c
@@ -367,8 +367,9 @@ DoCopy(ParseState *pstate, const CopyStmt *stmt,
 /*
  * Extract the CopyFormatOptions.header_line value from a DefElem.
  *
- * Parses the HEADER option for COPY, which can be a boolean, a non-negative
- * integer (number of lines to skip), or the special value "match".
+ * Parses the HEADER option for COPY, which can be a boolean, an integer greater
+ * than or equal to zero (number of lines to skip), or the special value
+ * "match".
  */
 static int
 defGetCopyHeaderOption(DefElem *def, bool is_from)
@@ -380,8 +381,8 @@ defGetCopyHeaderOption(DefElem *def, bool is_from)
 		return COPY_HEADER_TRUE;
 
 	/*
-	 * Allow 0, 1, "true", "false", "on", "off", a non-negative integer, or
-	 * "match".
+	 * Allow an integer value greater than or equal to zero, "true", "false",
+	 * "on", "off", or "match".
 	 */
 	switch (nodeTag(def->arg))
 	{
@@ -433,8 +434,8 @@ defGetCopyHeaderOption(DefElem *def, bool is_from)
 	}
 	ereport(ERROR,
 			(errcode(ERRCODE_SYNTAX_ERROR),
-			 errmsg("%s requires a Boolean value, a non-negative integer, "
-					"or the string \"match\"",
+			 errmsg("%s requires a Boolean value, an integer value greater "
+					"than or equal to zero, or the string \"match\"",
 					def->defname)));
 	return COPY_HEADER_FALSE;	/* keep compiler quiet */
 }
diff --git a/src/test/regress/expected/copy.out b/src/test/regress/expected/copy.out
index 24e0f472f14..797fae0e650 100644
--- a/src/test/regress/expected/copy.out
+++ b/src/test/regress/expected/copy.out
@@ -247,7 +247,7 @@ alter table header_copytest add column c text;
 copy header_copytest to stdout with (header match);
 ERROR:  cannot use "match" with HEADER in COPY TO
 copy header_copytest from stdin with (header wrong_choice);
-ERROR:  header requires a Boolean value, a non-negative integer, or the string "match"
+ERROR:  header requires a Boolean value, an integer value greater than or equal to zero, or the string "match"
 -- works
 copy header_copytest from stdin with (header match);
 copy header_copytest (c, a, b) from stdin with (header match);
diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out
index f3fdce23459..9c622e760a3 100644
--- a/src/test/regress/expected/copy2.out
+++ b/src/test/regress/expected/copy2.out
@@ -135,7 +135,7 @@ ERROR:  REJECT_LIMIT (0) must be greater than zero
 COPY x from stdin with (header -1);
 ERROR:  a negative integer value cannot be specified for header
 COPY x from stdin with (header 2.5);
-ERROR:  header requires a Boolean value, a non-negative integer, or the string "match"
+ERROR:  header requires a Boolean value, an integer value greater than or equal to zero, or the string "match"
 COPY x to stdout with (header 2);
 ERROR:  cannot use multi-line header in COPY TO
 -- too many columns in column list: should fail
-- 
2.51.2

