Improve the error message in COPY with HEADER option.
authorFujii Masao <fujii@postgresql.org>
Thu, 22 Jan 2026 01:13:07 +0000 (10:13 +0900)
committerFujii Masao <fujii@postgresql.org>
Thu, 22 Jan 2026 01:13:07 +0000 (10:13 +0900)
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: Alvaro Herrera <alvherre@kurilemu.de>
Reviewed-by: Steven Niu <niushiji@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
src/test/regress/expected/copy.out
src/test/regress/expected/copy2.out

index 9c51384ab92d60262c5eac7d8c0cd36fb4926032..1f6b24d66f89f76f12d20ed0331bb266fa123796 100644 (file)
@@ -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,9 +434,11 @@ 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\"",
-                   def->defname)));
+   /*- translator: first %s is the name of a COPY option, e.g. ON_ERROR,
+        second %s is the special value "match" for that option */
+            errmsg("%s requires a Boolean value, an integer value greater "
+                   "than or equal to zero, or the string \"%s\"",
+                   def->defname, "match")));
    return COPY_HEADER_FALSE;   /* keep compiler quiet */
 }
 
index 24e0f472f14ad3cd92c5536a80050b0bce016142..797fae0e650dc6ea1daed8eb9bc908f763fa54ef 100644 (file)
@@ -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);
index f3fdce23459aced41bf852fd7c46d1f616ec5ce8..9c622e760a3db44aff430068e2cb16ee9ce6a933 100644 (file)
@@ -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