Skip to content

Commit b725b7e

Browse files
committed
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
1 parent dd0a0cf commit b725b7e

File tree

9 files changed

+82
-78
lines changed

9 files changed

+82
-78
lines changed

doc/src/sgml/ref/copy.sgml

+10-10
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable
4343
FORCE_QUOTE { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
4444
FORCE_NOT_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
4545
FORCE_NULL { ( <replaceable class="parameter">column_name</replaceable> [, ...] ) | * }
46-
SAVE_ERROR_TO '<replaceable class="parameter">location</replaceable>'
46+
ON_ERROR '<replaceable class="parameter">error_action</replaceable>'
4747
ENCODING '<replaceable class="parameter">encoding_name</replaceable>'
4848
</synopsis>
4949
</refsynopsisdiv>
@@ -375,20 +375,20 @@ COPY { <replaceable class="parameter">table_name</replaceable> [ ( <replaceable
375375
</varlistentry>
376376

377377
<varlistentry>
378-
<term><literal>SAVE_ERROR_TO</literal></term>
378+
<term><literal>ON_ERROR</literal></term>
379379
<listitem>
380380
<para>
381-
Specifies to save error information to <replaceable class="parameter">
382-
location</replaceable> when there is malformed data in the input.
383-
Currently, only <literal>error</literal> (default) and <literal>none</literal>
381+
Specifies which <replaceable class="parameter">
382+
error_action</replaceable> to perform when there is malformed data in the input.
383+
Currently, only <literal>stop</literal> (default) and <literal>ignore</literal>
384384
values are supported.
385-
If the <literal>error</literal> value is specified,
385+
If the <literal>stop</literal> value is specified,
386386
<command>COPY</command> stops operation at the first error.
387-
If the <literal>none</literal> value is specified,
387+
If the <literal>ignore</literal> value is specified,
388388
<command>COPY</command> skips malformed data and continues copying data.
389389
The option is allowed only in <command>COPY FROM</command>.
390-
The <literal>none</literal> value is allowed only when
391-
not using <literal>binary</literal> format.
390+
Only <literal>stop</literal> value is allowed when
391+
using <literal>binary</literal> format.
392392
</para>
393393
</listitem>
394394
</varlistentry>
@@ -577,7 +577,7 @@ COPY <replaceable class="parameter">count</replaceable>
577577

578578
<para>
579579
<command>COPY</command> stops operation at the first error when
580-
<literal>SAVE_ERROR_TO</literal> is not specified. This
580+
<literal>ON_ERROR</literal> is not specified. This
581581
should not lead to problems in the event of a <command>COPY
582582
TO</command>, but the target table will already have received
583583
earlier rows in a <command>COPY FROM</command>. These rows will not

src/backend/commands/copy.c

+19-19
Original file line numberDiff line numberDiff line change
@@ -395,39 +395,39 @@ defGetCopyHeaderChoice(DefElem *def, bool is_from)
395395
}
396396

397397
/*
398-
* Extract a CopySaveErrorToChoice value from a DefElem.
398+
* Extract a CopyOnErrorChoice value from a DefElem.
399399
*/
400-
static CopySaveErrorToChoice
401-
defGetCopySaveErrorToChoice(DefElem *def, ParseState *pstate, bool is_from)
400+
static CopyOnErrorChoice
401+
defGetCopyOnErrorChoice(DefElem *def, ParseState *pstate, bool is_from)
402402
{
403403
char *sval;
404404

405405
if (!is_from)
406406
ereport(ERROR,
407407
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
408-
errmsg("COPY SAVE_ERROR_TO cannot be used with COPY TO"),
408+
errmsg("COPY ON_ERROR cannot be used with COPY TO"),
409409
parser_errposition(pstate, def->location)));
410410

411411
/*
412412
* If no parameter value given, assume the default value.
413413
*/
414414
if (def->arg == NULL)
415-
return COPY_SAVE_ERROR_TO_ERROR;
415+
return COPY_ON_ERROR_STOP;
416416

417417
/*
418-
* Allow "error", or "none" values.
418+
* Allow "stop", or "ignore" values.
419419
*/
420420
sval = defGetString(def);
421-
if (pg_strcasecmp(sval, "error") == 0)
422-
return COPY_SAVE_ERROR_TO_ERROR;
423-
if (pg_strcasecmp(sval, "none") == 0)
424-
return COPY_SAVE_ERROR_TO_NONE;
421+
if (pg_strcasecmp(sval, "stop") == 0)
422+
return COPY_ON_ERROR_STOP;
423+
if (pg_strcasecmp(sval, "ignore") == 0)
424+
return COPY_ON_ERROR_IGNORE;
425425

426426
ereport(ERROR,
427427
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
428-
errmsg("COPY save_error_to \"%s\" not recognized", sval),
428+
errmsg("COPY ON_ERROR \"%s\" not recognized", sval),
429429
parser_errposition(pstate, def->location)));
430-
return COPY_SAVE_ERROR_TO_ERROR; /* keep compiler quiet */
430+
return COPY_ON_ERROR_STOP; /* keep compiler quiet */
431431
}
432432

433433
/*
@@ -455,7 +455,7 @@ ProcessCopyOptions(ParseState *pstate,
455455
bool format_specified = false;
456456
bool freeze_specified = false;
457457
bool header_specified = false;
458-
bool save_error_to_specified = false;
458+
bool on_error_specified = false;
459459
ListCell *option;
460460

461461
/* Support external use for option sanity checking */
@@ -608,12 +608,12 @@ ProcessCopyOptions(ParseState *pstate,
608608
defel->defname),
609609
parser_errposition(pstate, defel->location)));
610610
}
611-
else if (strcmp(defel->defname, "save_error_to") == 0)
611+
else if (strcmp(defel->defname, "on_error") == 0)
612612
{
613-
if (save_error_to_specified)
613+
if (on_error_specified)
614614
errorConflictingDefElem(defel, pstate);
615-
save_error_to_specified = true;
616-
opts_out->save_error_to = defGetCopySaveErrorToChoice(defel, pstate, is_from);
615+
on_error_specified = true;
616+
opts_out->on_error = defGetCopyOnErrorChoice(defel, pstate, is_from);
617617
}
618618
else
619619
ereport(ERROR,
@@ -642,10 +642,10 @@ ProcessCopyOptions(ParseState *pstate,
642642
(errcode(ERRCODE_SYNTAX_ERROR),
643643
errmsg("cannot specify DEFAULT in BINARY mode")));
644644

645-
if (opts_out->binary && opts_out->save_error_to != COPY_SAVE_ERROR_TO_ERROR)
645+
if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
646646
ereport(ERROR,
647647
(errcode(ERRCODE_SYNTAX_ERROR),
648-
errmsg("cannot specify SAVE_ERROR_TO in BINARY mode")));
648+
errmsg("only ON_ERROR STOP is allowed in BINARY mode")));
649649

650650
/* Set defaults for omitted options */
651651
if (!opts_out->delim)

src/backend/commands/copyfrom.c

+10-10
Original file line numberDiff line numberDiff line change
@@ -657,7 +657,7 @@ CopyFrom(CopyFromState cstate)
657657
Assert(cstate->rel);
658658
Assert(list_length(cstate->range_table) == 1);
659659

660-
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR)
660+
if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
661661
Assert(cstate->escontext);
662662

663663
/*
@@ -996,14 +996,14 @@ CopyFrom(CopyFromState cstate)
996996
if (!NextCopyFrom(cstate, econtext, myslot->tts_values, myslot->tts_isnull))
997997
break;
998998

999-
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR &&
999+
if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
10001000
cstate->escontext->error_occurred)
10011001
{
10021002
/*
1003-
* Soft error occured, skip this tuple and save error information
1004-
* according to SAVE_ERROR_TO.
1003+
* Soft error occured, skip this tuple and deal with error
1004+
* information according to ON_ERROR.
10051005
*/
1006-
if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE)
1006+
if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
10071007

10081008
/*
10091009
* Just make ErrorSaveContext ready for the next NextCopyFrom.
@@ -1307,7 +1307,7 @@ CopyFrom(CopyFromState cstate)
13071307
/* Done, clean up */
13081308
error_context_stack = errcallback.previous;
13091309

1310-
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR &&
1310+
if (cstate->opts.on_error != COPY_ON_ERROR_STOP &&
13111311
cstate->num_errors > 0)
13121312
ereport(NOTICE,
13131313
errmsg_plural("%llu row was skipped due to data type incompatibility",
@@ -1450,18 +1450,18 @@ BeginCopyFrom(ParseState *pstate,
14501450
}
14511451
}
14521452

1453-
/* Set up soft error handler for SAVE_ERROR_TO */
1454-
if (cstate->opts.save_error_to != COPY_SAVE_ERROR_TO_ERROR)
1453+
/* Set up soft error handler for ON_ERROR */
1454+
if (cstate->opts.on_error != COPY_ON_ERROR_STOP)
14551455
{
14561456
cstate->escontext = makeNode(ErrorSaveContext);
14571457
cstate->escontext->type = T_ErrorSaveContext;
14581458
cstate->escontext->error_occurred = false;
14591459

14601460
/*
1461-
* Currently we only support COPY_SAVE_ERROR_TO_NONE. We'll add other
1461+
* Currently we only support COPY_ON_ERROR_IGNORE. We'll add other
14621462
* options later
14631463
*/
1464-
if (cstate->opts.save_error_to == COPY_SAVE_ERROR_TO_NONE)
1464+
if (cstate->opts.on_error == COPY_ON_ERROR_IGNORE)
14651465
cstate->escontext->details_wanted = false;
14661466
}
14671467
else

src/backend/commands/copyfromparse.c

+5-1
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,11 @@ NextCopyFrom(CopyFromState cstate, ExprContext *econtext,
956956

957957
values[m] = ExecEvalExpr(defexprs[m], econtext, &nulls[m]);
958958
}
959-
/* If SAVE_ERROR_TO is specified, skip rows with soft errors */
959+
960+
/*
961+
* If ON_ERROR is specified with IGNORE, skip rows with soft
962+
* errors
963+
*/
960964
else if (!InputFunctionCallSafe(&in_functions[m],
961965
string,
962966
typioparams[m],

src/bin/psql/tab-complete.c

+4-4
Original file line numberDiff line numberDiff line change
@@ -2899,15 +2899,15 @@ psql_completion(const char *text, int start, int end)
28992899
COMPLETE_WITH("FORMAT", "FREEZE", "DELIMITER", "NULL",
29002900
"HEADER", "QUOTE", "ESCAPE", "FORCE_QUOTE",
29012901
"FORCE_NOT_NULL", "FORCE_NULL", "ENCODING", "DEFAULT",
2902-
"SAVE_ERROR_TO");
2902+
"ON_ERROR");
29032903

29042904
/* Complete COPY <sth> FROM|TO filename WITH (FORMAT */
29052905
else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "FORMAT"))
29062906
COMPLETE_WITH("binary", "csv", "text");
29072907

2908-
/* Complete COPY <sth> FROM filename WITH (SAVE_ERROR_TO */
2909-
else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "SAVE_ERROR_TO"))
2910-
COMPLETE_WITH("error", "none");
2908+
/* Complete COPY <sth> FROM filename WITH (ON_ERROR */
2909+
else if (Matches("COPY|\\copy", MatchAny, "FROM|TO", MatchAny, "WITH", "(", "ON_ERROR"))
2910+
COMPLETE_WITH("stop", "ignore");
29112911

29122912
/* Complete COPY <sth> FROM <sth> WITH (<options>) */
29132913
else if (Matches("COPY|\\copy", MatchAny, "FROM", MatchAny, "WITH", MatchAny))

src/include/commands/copy.h

+5-5
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ typedef enum CopyHeaderChoice
3434
* Represents where to save input processing errors. More values to be added
3535
* in the future.
3636
*/
37-
typedef enum CopySaveErrorToChoice
37+
typedef enum CopyOnErrorChoice
3838
{
39-
COPY_SAVE_ERROR_TO_ERROR = 0, /* immediately throw errors */
40-
COPY_SAVE_ERROR_TO_NONE, /* ignore errors */
41-
} CopySaveErrorToChoice;
39+
COPY_ON_ERROR_STOP = 0, /* immediately throw errors, default */
40+
COPY_ON_ERROR_IGNORE, /* ignore errors */
41+
} CopyOnErrorChoice;
4242

4343
/*
4444
* A struct to hold COPY options, in a parsed form. All of these are related
@@ -72,7 +72,7 @@ typedef struct CopyFormatOptions
7272
bool force_null_all; /* FORCE_NULL *? */
7373
bool *force_null_flags; /* per-column CSV FN flags */
7474
bool convert_selectively; /* do selective binary conversion? */
75-
CopySaveErrorToChoice save_error_to; /* where to save error information */
75+
CopyOnErrorChoice on_error; /* what to do when error happened */
7676
List *convert_select; /* list of column names (can be NIL) */
7777
} CopyFormatOptions;
7878

src/test/regress/expected/copy2.out

+18-18
Original file line numberDiff line numberDiff line change
@@ -77,21 +77,21 @@ COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii');
7777
ERROR: conflicting or redundant options
7878
LINE 1: COPY x from stdin (encoding 'sql_ascii', encoding 'sql_ascii...
7979
^
80-
COPY x from stdin (save_error_to none,save_error_to none);
80+
COPY x from stdin (on_error ignore, on_error ignore);
8181
ERROR: conflicting or redundant options
82-
LINE 1: COPY x from stdin (save_error_to none,save_error_to none);
83-
^
82+
LINE 1: COPY x from stdin (on_error ignore, on_error ignore);
83+
^
8484
-- incorrect options
8585
COPY x to stdin (format BINARY, delimiter ',');
8686
ERROR: cannot specify DELIMITER in BINARY mode
8787
COPY x to stdin (format BINARY, null 'x');
8888
ERROR: cannot specify NULL in BINARY mode
89-
COPY x from stdin (format BINARY, save_error_to none);
90-
ERROR: cannot specify SAVE_ERROR_TO in BINARY mode
91-
COPY x to stdin (save_error_to none);
92-
ERROR: COPY SAVE_ERROR_TO cannot be used with COPY TO
93-
LINE 1: COPY x to stdin (save_error_to none);
94-
^
89+
COPY x from stdin (format BINARY, on_error ignore);
90+
ERROR: only ON_ERROR STOP is allowed in BINARY mode
91+
COPY x from stdin (on_error unsupported);
92+
ERROR: COPY ON_ERROR "unsupported" not recognized
93+
LINE 1: COPY x from stdin (on_error unsupported);
94+
^
9595
COPY x to stdin (format TEXT, force_quote(a));
9696
ERROR: COPY FORCE_QUOTE requires CSV mode
9797
COPY x from stdin (format CSV, force_quote(a));
@@ -104,9 +104,9 @@ COPY x to stdout (format TEXT, force_null(a));
104104
ERROR: COPY FORCE_NULL requires CSV mode
105105
COPY x to stdin (format CSV, force_null(a));
106106
ERROR: COPY FORCE_NULL cannot be used with COPY TO
107-
COPY x to stdin (format BINARY, save_error_to unsupported);
108-
ERROR: COPY SAVE_ERROR_TO cannot be used with COPY TO
109-
LINE 1: COPY x to stdin (format BINARY, save_error_to unsupported);
107+
COPY x to stdin (format BINARY, on_error unsupported);
108+
ERROR: COPY ON_ERROR cannot be used with COPY TO
109+
LINE 1: COPY x to stdin (format BINARY, on_error unsupported);
110110
^
111111
-- too many columns in column list: should fail
112112
COPY x (a, b, c, d, e, d, c) from stdin;
@@ -724,12 +724,12 @@ SELECT * FROM instead_of_insert_tbl;
724724
(2 rows)
725725

726726
COMMIT;
727-
-- tests for SAVE_ERROR_TO option
727+
-- tests for on_error option
728728
CREATE TABLE check_ign_err (n int, m int[], k int);
729-
COPY check_ign_err FROM STDIN WITH (save_error_to error);
729+
COPY check_ign_err FROM STDIN WITH (on_error stop);
730730
ERROR: invalid input syntax for type integer: "a"
731731
CONTEXT: COPY check_ign_err, line 2, column n: "a"
732-
COPY check_ign_err FROM STDIN WITH (save_error_to none);
732+
COPY check_ign_err FROM STDIN WITH (on_error ignore);
733733
NOTICE: 4 rows were skipped due to data type incompatibility
734734
SELECT * FROM check_ign_err;
735735
n | m | k
@@ -740,15 +740,15 @@ SELECT * FROM check_ign_err;
740740

741741
-- test datatype error that can't be handled as soft: should fail
742742
CREATE TABLE hard_err(foo widget);
743-
COPY hard_err FROM STDIN WITH (save_error_to none);
743+
COPY hard_err FROM STDIN WITH (on_error ignore);
744744
ERROR: invalid input syntax for type widget: "1"
745745
CONTEXT: COPY hard_err, line 1, column foo: "1"
746746
-- test missing data: should fail
747-
COPY check_ign_err FROM STDIN WITH (save_error_to none);
747+
COPY check_ign_err FROM STDIN WITH (on_error ignore);
748748
ERROR: missing data for column "k"
749749
CONTEXT: COPY check_ign_err, line 1: "1 {1}"
750750
-- test extra data: should fail
751-
COPY check_ign_err FROM STDIN WITH (save_error_to none);
751+
COPY check_ign_err FROM STDIN WITH (on_error ignore);
752752
ERROR: extra data after last expected column
753753
CONTEXT: COPY check_ign_err, line 1: "1 {1} 3 abc"
754754
-- clean up

0 commit comments

Comments
 (0)