From e3098178b469feb98dbeb90fe9ca1b23874a7ffe Mon Sep 17 00:00:00 2001 From: "Chao Li (Evan)" Date: Thu, 5 Nov 2026 14:36:22 +0800 Subject: [PATCH v1] 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 --- src/backend/commands/copyfromparse.c | 6 ++++-- src/test/regress/expected/copy2.out | 13 ++++++++++--- src/test/regress/sql/copy2.sql | 12 +++++++++++- 3 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c index 06450535779..0361fa0f2da 100644 --- a/src/backend/commands/copyfromparse.c +++ b/src/backend/commands/copyfromparse.c @@ -1170,9 +1170,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 df6fcd91799..b79c7b226d0 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 @@ -883,14 +887,17 @@ CONTEXT: COPY hard_err, line 1, column foo: "1" COPY check_ign_err FROM STDIN WITH (on_error ignore); ERROR: missing data for column "k" CONTEXT: COPY check_ign_err, line 1: "1 {1}" --- test extra data: should fail +-- test extra data after an ignored row: should fail with the current line 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 ec6f5e8cfdc..3ab5443235d 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 @@ -669,11 +673,17 @@ COPY check_ign_err FROM STDIN WITH (on_error ignore); 1 {1} \. --- test extra data: should fail +-- test extra data after an ignored row: should fail with the current line 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)