Rename COPY option from SAVE_ERROR_TO to ON_ERROR

The option names now are "stop" (default) and "ignore".  The future options
could be "file 'filename.log'" and "table 'tablename'".

Discussion: https://postgr.es/m/20240117.164859.2242646601795501168.horikyota.ntt%40gmail.com
Author: Jian He
Reviewed-by: Atsushi Torikoshi
This commit is contained in:
Alexander Korotkov 2024-01-19 15:08:40 +02:00
parent dd0a0cfc81
commit b725b7eec4
9 changed files with 82 additions and 78 deletions

View File

@ -43,7 +43,7 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable
FORCE_QUOTE { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * } FORCE_QUOTE { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
FORCE_NOT_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * } FORCE_NOT_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
FORCE_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * } FORCE_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
SAVE_ERROR_TO '<replaceable class="parameter">location</replaceable>' ON_ERROR '<replaceable class="parameter">error_action</replaceable>'
ENCODING '<replaceable class="parameter">encoding_name</replaceable>' ENCODING '<replaceable class="parameter">encoding_name</replaceable>'
</synopsis> </synopsis>
</refsynopsisdiv> </refsynopsisdiv>
@ -375,20 +375,20 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><literal>SAVE_ERROR_TO</literal></term> <term><literal>ON_ERROR</literal></term>
<listitem> <listitem>
<para> <para>
Specifies to save error information to <replaceable class="parameter"> Specifies which <replaceable class="parameter">
location</replaceable> when there is malformed data in the input. error_action</replaceable> to perform when there is malformed data in the input.
Currently, only <literal>error</literal> (default) and <literal>none</literal> Currently, only <literal>stop</literal> (default) and <literal>ignore</literal>
values are supported. values are supported.
If the <literal>error</literal> value is specified, If the <literal>stop</literal> value is specified,
<command>COPY</command> stops operation at the first error. <command>COPY</command> stops operation at the first error.
If the <literal>none</literal> value is specified, If the <literal>ignore</literal> value is specified,
<command>COPY</command> skips malformed data and continues copying data. <command>COPY</command> skips malformed data and continues copying data.
The option is allowed only in <command>COPY FROM</command>. The option is allowed only in <command>COPY FROM</command>.
The <literal>none</literal> value is allowed only when Only <literal>stop</literal> value is allowed when
not using <literal>binary</literal> format. using <literal>binary</literal> format.
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>
@ -577,7 +577,7 @@ COPY <replaceable class="parameter">count</replaceable>
<para> <para>
<command>COPY</command> stops operation at the first error when <command>COPY</command> stops operation at the first error when
<literal>SAVE_ERROR_TO</literal> is not specified. This <literal>ON_ERROR</literal> is not specified. This
should not lead to problems in the event of a <command>COPY should not lead to problems in the event of a <command>COPY
TO</command>, but the target table will already have received TO</command>, but the target table will already have received
earlier rows in a <command>COPY FROM</command>. These rows will not earlier rows in a <command>COPY FROM</command>. These rows will not

View File

@ -395,39 +395,39 @@ defGetCopyHeaderChoice(DefElem *def, bool is_from)
} }
/* /*
* Extract a CopySaveErrorToChoice value from a DefElem. * Extract a CopyOnErrorChoice value from a DefElem.
*/ */
static CopySaveErrorToChoice static CopyOnErrorChoice
defGetCopySaveErrorToChoice(DefElem *def, ParseState *pstate, bool is_from) defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
{ {
char *sval; char *sval;
if (!is_from) if (!is_from)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("COPY SAVE_ERROR_TO cannot be used with COPY TO"), errmsg("COPY ON_ERROR cannot be used with COPY TO"),
parser_errposition(pstate, def->location))); parser_errposition(pstate, def->location)));
/* /*
* If no parameter value given, assume the default value. * If no parameter value given, assume the default value.
*/ */
if (def->arg == NULL) if (def->arg == NULL)
return COPY_SAVE_ERROR_TO_ERROR; return COPY_ON_ERROR_STOP;
/* /*
* Allow "error", or "none" values. * Allow "stop", or "ignore" values.
*/ */
sval = defGetString(def); sval = defGetString(def);
if (pg_strcasecmp(sval, "error") == 0) if (pg_strcasecmp(sval, "stop") == 0)
return COPY_SAVE_ERROR_TO_ERROR; return COPY_ON_ERROR_STOP;
if (pg_strcasecmp(sval, "none") == 0) if (pg_strcasecmp(sval, "ignore") == 0)
return COPY_SAVE_ERROR_TO_NONE; return COPY_ON_ERROR_IGNORE;
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("COPY save_error_to \"%s\" not recognized", sval), errmsg("COPY ON_ERROR \"%s\" not recognized", sval),
parser_errposition(pstate, def->location))); parser_errposition(pstate, def->location)));
return COPY_SAVE_ERROR_TO_ERROR; /* keep compiler quiet */ return COPY_ON_ERROR_STOP; /* keep compiler quiet */
} }
/* /*
@ -455,7 +455,7 @@ ProcessCopyOptions(ParseState *pstate,
bool format_specified = false; bool format_specified = false;
bool freeze_specified = false; bool freeze_specified = false;
bool header_specified = false; bool header_specified = false;
bool save_error_to_specified = false; bool on_error_specified = false;
ListCell *option; ListCell *option;
/* Support external use for option sanity checking */ /* Support external use for option sanity checking */
@ -608,12 +608,12 @@ ProcessCopyOptions(ParseState *pstate,
defel->defname), defel->defname),
parser_errposition(pstate, defel->location))); parser_errposition(pstate, defel->location)));
} }
else if (strcmp(defel->defname, "save_error_to") == 0) else if (strcmp(defel->defname, "on_error") == 0)
{ {
if (save_error_to_specified) if (on_error_specified)
errorConflictingDefElem(defel, pstate); errorConflictingDefElem(defel, pstate);
save_error_to_specified = true; on_error_specified = true;
opts_out->save_error_to = defGetCopySaveErrorToChoice(defel, pstate, is_from); opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
} }
else else
ereport(ERROR, ereport(ERROR,
@ -642,10 +642,10 @@ ProcessCopyOptions(ParseState *pstate,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot specify DEFAULT in BINARY mode"))); errmsg("cannot specify DEFAULT in BINARY mode")));
if (opts_out->binary && opts_out->save_error_to != COPY_SAVE_ERROR_TO_ERROR) if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_SYNTAX_ERROR), (errcode(ERRCODE_SYNTAX_ERROR),
errmsg("cannot specify SAVE_ERROR_TO in BINARY mode"))); errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
/* Set defaults for omitted options */ /* Set defaults for omitted options */
if (!opts_out->delim) if (!opts_out->delim)

View File

@ -657,7 +657,7 @@ CopyFrom(CopyFromState cstate)
Assert(cstate->rel); Assert(cstate->rel);
Assert(list_length(cstate->range_table) == 1); Assert(list_length(cstate->range_table) == 1);
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR) if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
Assert(cstate->escontext); Assert(cstate->escontext);
/* /*
@ -996,14 +996,14 @@ CopyFrom(CopyFromState cstate)
if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull)) if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
break; break;
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR && if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
cstate->escontext->error_occurred) cstate->escontext->error_occurred)
{ {
/* /*
* Soft error occured, skip this tuple and save error information * Soft error occured, skip this tuple and deal with error
* according to SAVE_ERROR_TO. * information according to ON_ERROR.
*/ */
if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE) if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
/* /*
* Just make ErrorSaveContext ready for the next NextCopyFrom. * Just make ErrorSaveContext ready for the next NextCopyFrom.
@ -1307,7 +1307,7 @@ CopyFrom(CopyFromState cstate)
/* Done, clean up */ /* Done, clean up */
error_context_stack = errcallback.previous; error_context_stack = errcallback.previous;
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR && if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
cstate->num_errors > 0) cstate->num_errors > 0)
ereport(NOTICE, ereport(NOTICE,
errmsg_plural("%llu row was skipped due to data type incompatibility", errmsg_plural("%llu row was skipped due to data type incompatibility",
@ -1450,18 +1450,18 @@ BeginCopyFrom(ParseState *pstate,
} }
} }
/* Set up soft error handler for SAVE_ERROR_TO */ /* Set up soft error handler for ON_ERROR */
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR) if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
{ {
cstate->escontext = makeNode(ErrorSaveContext); cstate->escontext = makeNode(ErrorSaveContext);
cstate->escontext->type = T_ErrorSaveContext; cstate->escontext->type = T_ErrorSaveContext;
cstate->escontext->error_occurred = false; cstate->escontext->error_occurred = false;
/* /*
* Currently we only support COPY_SAVE_ERROR_TO_NONE. We'll add other * Currently we only support COPY_ON_ERROR_IGNORE. We'll add other
* options later * options later
*/ */
if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE) if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
cstate->escontext->details_wanted = false; cstate->escontext->details_wanted = false;
} }
else else

View File

@ -956,7 +956,11 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]); values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]);
} }
/* If SAVE_ERROR_TO is specified, skip rows with soft errors */
/*
* If ON_ERROR is specified with IGNORE, skip rows with soft
* errors
*/
else if (!InputFunctionCallSafe(&in_functions[m], else if (!InputFunctionCallSafe(&in_functions[m],
string, string,
typioparams[m], typioparams[m],

View File

@ -2899,15 +2899,15 @@ psql_completion(const char *text, int start, int end)
COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL", COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
"HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE", "HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
"FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT", "FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT",
"SAVE_ERROR_TO"); "ON_ERROR");
/* Complete COPY <sth> FROM|TO filename WITH (FORMAT */ /* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT")) else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
COMPLETE_WITH("binary", "csv", "text"); COMPLETE_WITH("binary", "csv", "text");
/* Complete COPY <sth> FROM filename WITH (SAVE_ERROR_TO */ /* Complete COPY <sth> FROM filename WITH (ON_ERROR */
else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "SAVE_ERROR_TO")) else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "ON_ERROR"))
COMPLETE_WITH("error", "none"); COMPLETE_WITH("stop", "ignore");
/* Complete COPY <sth> FROM <sth> WITH (<options>) */ /* Complete COPY <sth> FROM <sth> WITH (<options>) */
else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny)) else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))

View File

@ -34,11 +34,11 @@ typedef enum CopyHeaderChoice
* Represents where to save input processing errors. More values to be added * Represents where to save input processing errors. More values to be added
* in the future. * in the future.
*/ */
typedef enum CopySaveErrorToChoice typedef enum CopyOnErrorChoice
{ {
COPY_SAVE_ERROR_TO_ERROR = 0, /* immediately throw errors */ COPY_ON_ERROR_STOP = 0, /* immediately throw errors, default */
COPY_SAVE_ERROR_TO_NONE, /* ignore errors */ COPY_ON_ERROR_IGNORE, /* ignore errors */
} CopySaveErrorToChoice; } CopyOnErrorChoice;
/* /*
* A struct to hold COPY options, in a parsed form. All of these are related * A struct to hold COPY options, in a parsed form. All of these are related
@ -72,7 +72,7 @@ typedef struct CopyFormatOptions
bool force_null_all; /* FORCE_NULL *? */ bool force_null_all; /* FORCE_NULL *? */
bool *force_null_flags; /* per-column CSV FN flags */ bool *force_null_flags; /* per-column CSV FN flags */
bool convert_selectively; /* do selective binary conversion? */ bool convert_selectively; /* do selective binary conversion? */
CopySaveErrorToChoice save_error_to; /* where to save error information */ CopyOnErrorChoice on_error; /* what to do when error happened */
List *convert_select; /* list of column names (can be NIL) */ List *convert_select; /* list of column names (can be NIL) */
} CopyFormatOptions; } CopyFormatOptions;

View File

@ -77,20 +77,20 @@ COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
ERROR: conflicting or redundant options ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii... LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
^ ^
COPY x from stdin (save_error_to none,save_error_to none); COPY x from stdin (on_error ignore, on_error ignore);
ERROR: conflicting or redundant options ERROR: conflicting or redundant options
LINE 1: COPY x from stdin (save_error_to none,save_error_to none); LINE 1: COPY x from stdin (on_error ignore, on_error ignore);
^ ^
-- incorrect options -- incorrect options
COPY x to stdin (format BINARY, delimiter ','); COPY x to stdin (format BINARY, delimiter ',');
ERROR: cannot specify DELIMITER in BINARY mode ERROR: cannot specify DELIMITER in BINARY mode
COPY x to stdin (format BINARY, null 'x'); COPY x to stdin (format BINARY, null 'x');
ERROR: cannot specify NULL in BINARY mode ERROR: cannot specify NULL in BINARY mode
COPY x from stdin (format BINARY, save_error_to none); COPY x from stdin (format BINARY, on_error ignore);
ERROR: cannot specify SAVE_ERROR_TO in BINARY mode ERROR: only ON_ERROR STOP is allowed in BINARY mode
COPY x to stdin (save_error_to none); COPY x from stdin (on_error unsupported);
ERROR: COPY SAVE_ERROR_TO cannot be used with COPY TO ERROR: COPY ON_ERROR "unsupported" not recognized
LINE 1: COPY x to stdin (save_error_to none); LINE 1: COPY x from stdin (on_error unsupported);
^ ^
COPY x to stdin (format TEXT, force_quote(a)); COPY x to stdin (format TEXT, force_quote(a));
ERROR: COPY FORCE_QUOTE requires CSV mode ERROR: COPY FORCE_QUOTE requires CSV mode
@ -104,9 +104,9 @@ COPY x to stdout (format TEXT, force_null(a));
ERROR: COPY FORCE_NULL requires CSV mode ERROR: COPY FORCE_NULL requires CSV mode
COPY x to stdin (format CSV, force_null(a)); COPY x to stdin (format CSV, force_null(a));
ERROR: COPY FORCE_NULL cannot be used with COPY TO ERROR: COPY FORCE_NULL cannot be used with COPY TO
COPY x to stdin (format BINARY, save_error_to unsupported); COPY x to stdin (format BINARY, on_error unsupported);
ERROR: COPY SAVE_ERROR_TO cannot be used with COPY TO ERROR: COPY ON_ERROR cannot be used with COPY TO
LINE 1: COPY x to stdin (format BINARY, save_error_to unsupported); LINE 1: COPY x to stdin (format BINARY, on_error unsupported);
^ ^
-- too many columns in column list: should fail -- too many columns in column list: should fail
COPY x (a, b, c, d, e, d, c) from stdin; COPY x (a, b, c, d, e, d, c) from stdin;
@ -724,12 +724,12 @@ SELECT * FROM instead_of_insert_tbl;
(2 rows) (2 rows)
COMMIT; COMMIT;
-- tests for SAVE_ERROR_TO option -- tests for on_error option
CREATE TABLE check_ign_err (n int, m int[], k int); CREATE TABLE check_ign_err (n int, m int[], k int);
COPY check_ign_err FROM STDIN WITH (save_error_to error); COPY check_ign_err FROM STDIN WITH (on_error stop);
ERROR: invalid input syntax for type integer: "a" ERROR: invalid input syntax for type integer: "a"
CONTEXT: COPY check_ign_err, line 2, column n: "a" CONTEXT: COPY check_ign_err, line 2, column n: "a"
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
NOTICE: 4 rows were skipped due to data type incompatibility NOTICE: 4 rows were skipped due to data type incompatibility
SELECT * FROM check_ign_err; SELECT * FROM check_ign_err;
n | m | k n | m | k
@ -740,15 +740,15 @@ SELECT * FROM check_ign_err;
-- test datatype error that can't be handled as soft: should fail -- test datatype error that can't be handled as soft: should fail
CREATE TABLE hard_err(foo widget); CREATE TABLE hard_err(foo widget);
COPY hard_err FROM STDIN WITH (save_error_to none); COPY hard_err FROM STDIN WITH (on_error ignore);
ERROR: invalid input syntax for type widget: "1" ERROR: invalid input syntax for type widget: "1"
CONTEXT: COPY hard_err, line 1, column foo: "1" CONTEXT: COPY hard_err, line 1, column foo: "1"
-- test missing data: should fail -- test missing data: should fail
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
ERROR: missing data for column "k" ERROR: missing data for column "k"
CONTEXT: COPY check_ign_err, line 1: "1 {1}" CONTEXT: COPY check_ign_err, line 1: "1 {1}"
-- test extra data: should fail -- test extra data: should fail
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
ERROR: extra data after last expected column ERROR: extra data after last expected column
CONTEXT: COPY check_ign_err, line 1: "1 {1} 3 abc" CONTEXT: COPY check_ign_err, line 1: "1 {1} 3 abc"
-- clean up -- clean up

View File

@ -66,20 +66,20 @@ COPY x from stdin (force_not_null (a), force_not_null (b));
COPY x from stdin (force_null (a), force_null (b)); COPY x from stdin (force_null (a), force_null (b));
COPY x from stdin (convert_selectively (a), convert_selectively (b)); COPY x from stdin (convert_selectively (a), convert_selectively (b));
COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii'); COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
COPY x from stdin (save_error_to none,save_error_to none); COPY x from stdin (on_error ignore, on_error ignore);
-- incorrect options -- incorrect options
COPY x to stdin (format BINARY, delimiter ','); COPY x to stdin (format BINARY, delimiter ',');
COPY x to stdin (format BINARY, null 'x'); COPY x to stdin (format BINARY, null 'x');
COPY x from stdin (format BINARY, save_error_to none); COPY x from stdin (format BINARY, on_error ignore);
COPY x to stdin (save_error_to none); COPY x from stdin (on_error unsupported);
COPY x to stdin (format TEXT, force_quote(a)); COPY x to stdin (format TEXT, force_quote(a));
COPY x from stdin (format CSV, force_quote(a)); COPY x from stdin (format CSV, force_quote(a));
COPY x to stdout (format TEXT, force_not_null(a)); COPY x to stdout (format TEXT, force_not_null(a));
COPY x to stdin (format CSV, force_not_null(a)); COPY x to stdin (format CSV, force_not_null(a));
COPY x to stdout (format TEXT, force_null(a)); COPY x to stdout (format TEXT, force_null(a));
COPY x to stdin (format CSV, force_null(a)); COPY x to stdin (format CSV, force_null(a));
COPY x to stdin (format BINARY, save_error_to unsupported); COPY x to stdin (format BINARY, on_error unsupported);
-- too many columns in column list: should fail -- too many columns in column list: should fail
COPY x (a, b, c, d, e, d, c) from stdin; COPY x (a, b, c, d, e, d, c) from stdin;
@ -498,9 +498,9 @@ test1
SELECT * FROM instead_of_insert_tbl; SELECT * FROM instead_of_insert_tbl;
COMMIT; COMMIT;
-- tests for SAVE_ERROR_TO option -- tests for on_error option
CREATE TABLE check_ign_err (n int, m int[], k int); CREATE TABLE check_ign_err (n int, m int[], k int);
COPY check_ign_err FROM STDIN WITH (save_error_to error); COPY check_ign_err FROM STDIN WITH (on_error stop);
1 {1} 1 1 {1} 1
a {2} 2 a {2} 2
3 {3} 3333333333 3 {3} 3333333333
@ -508,7 +508,7 @@ a {2} 2
5 {5} 5 5 {5} 5
\. \.
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
1 {1} 1 1 {1} 1
a {2} 2 a {2} 2
3 {3} 3333333333 3 {3} 3333333333
@ -520,17 +520,17 @@ SELECT * FROM check_ign_err;
-- test datatype error that can't be handled as soft: should fail -- test datatype error that can't be handled as soft: should fail
CREATE TABLE hard_err(foo widget); CREATE TABLE hard_err(foo widget);
COPY hard_err FROM STDIN WITH (save_error_to none); COPY hard_err FROM STDIN WITH (on_error ignore);
1 1
\. \.
-- test missing data: should fail -- test missing data: should fail
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
1 {1} 1 {1}
\. \.
-- test extra data: should fail -- test extra data: should fail
COPY check_ign_err FROM STDIN WITH (save_error_to none); COPY check_ign_err FROM STDIN WITH (on_error ignore);
1 {1} 3 abc 1 {1} 3 abc
\. \.

View File

@ -478,6 +478,7 @@ CopyHeaderChoice
CopyInsertMethod CopyInsertMethod
CopyMultiInsertBuffer CopyMultiInsertBuffer
CopyMultiInsertInfo CopyMultiInsertInfo
CopyOnErrorChoice
CopySource CopySource
CopyStmt CopyStmt
CopyToState CopyToState
@ -4041,4 +4042,3 @@ manifest_writer
rfile rfile
ws_options ws_options
ws_file_info ws_file_info
CopySaveErrorToChoice