From 732142426c191ac2224beb69850d98a45bb7d8a3 Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Thu, 5 Nov 2026 14:36:22 +0800 Subject: [PATCH v2] Fix stale column context after COPY FROM conversion errors ON_ERROR ignore returns before clearing cur_attname and cur_attval, causing subsequent row-format errors to report stale column context. Clear these fields before returning. Also remove the ON_ERROR set_null continue that bypasses the same cleanup, so errors such as missing columns report the whole input row. Add regression coverage for both cases in copy2. Author: Chao Li Reviewed-by: Yilin Zhang Discussion: https://postgr.es/m/A603A132-9AF1-43B1-9194-318B6FA9C0E4@gmail.com --- src/backend/commands/copyfromparse.c | 6 ++++-- src/test/regress/expected/copy2.out | 11 +++++++++-- src/test/regress/sql/copy2.sql | 10 ++++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c index e6cf907ad28..8eefbc25cdd 100644 --- a/src/backend/commands/copyfromparse.c +++ b/src/backend/commands/copyfromparse.c @@ -1174,9 +1174,11 @@ CopyFromTextLikeOneRow(CopyFromState cstate, ExprContext *econtext, } if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE) + { + cstate->cur_attname = NULL; + cstate->cur_attval = NULL; return true; - else if (cstate->opts.on_error == COPY_ON_ERROR_SET_NULL) - continue; + } } cstate->cur_attname = NULL; diff --git a/src/test/regress/expected/copy2.out b/src/test/regress/expected/copy2.out index 690568db4be..0019526bac1 100644 --- a/src/test/regress/expected/copy2.out +++ b/src/test/regress/expected/copy2.out @@ -826,6 +826,10 @@ CONTEXT: COPY t_on_error_null, line 1, column a: "-1" COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); ERROR: missing data for column "c" CONTEXT: COPY t_on_error_null, line 1: "1,1" +-- fail, less data after a conversion error. +COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); +ERROR: missing data for column "c" +CONTEXT: COPY t_on_error_null, line 1: "1,bad" -- fail, extra data. COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); ERROR: extra data after last expected column @@ -894,11 +898,14 @@ CONTEXT: COPY check_ign_err, line 2: "2 {2} 2 extra" -- test extra data: should fail COPY check_ign_err FROM STDIN WITH (on_error ignore); ERROR: extra data after last expected column -CONTEXT: COPY check_ign_err, line 1: "1 {1} 3 abc" +CONTEXT: COPY check_ign_err, line 2: "1 {1} 3 abc" +COPY check_ign_err FROM STDIN WITH (format csv, on_error ignore); +ERROR: extra data after last expected column +CONTEXT: COPY check_ign_err, line 2: "1,{1},3,abc" -- tests for reject_limit option COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 3); ERROR: skipped more than REJECT_LIMIT (3) rows due to data type incompatibility -CONTEXT: COPY check_ign_err, line 5, column n: "" +CONTEXT: COPY check_ign_err, line 5: "" COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 4); NOTICE: 4 rows were skipped due to data type incompatibility -- clean up diff --git a/src/test/regress/sql/copy2.sql b/src/test/regress/sql/copy2.sql index 71b7e31dac5..3138f268eca 100644 --- a/src/test/regress/sql/copy2.sql +++ b/src/test/regress/sql/copy2.sql @@ -624,6 +624,10 @@ COPY t_on_error_null FROM STDIN WITH (on_error set_null); -- fail COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); 1,1 \. +-- fail, less data after a conversion error. +COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); +1,bad +\. -- fail, extra data. COPY t_on_error_null FROM STDIN WITH (delimiter ',', on_error set_null); 1,2,3,4 @@ -682,9 +686,15 @@ COPY check_ign_err FROM STDIN WITH (on_error ignore); -- test extra data: should fail COPY check_ign_err FROM STDIN WITH (on_error ignore); +bad {1} 3 1 {1} 3 abc \. +COPY check_ign_err FROM STDIN WITH (format csv, on_error ignore); +bad,{1},3 +1,{1},3,abc +\. + -- tests for reject_limit option COPY check_ign_err FROM STDIN WITH (on_error ignore, reject_limit 3); 6 {6} 6 -- 2.50.1 (Apple Git-155)