Skip to content

Commit 1468ecb

Browse files
jianhe-funCommitfest Bot
authored andcommitted
introduce CopyFormat refactor CopyFormatOptions
Currently, COPY command format is determined by two booleans, binary and csv_mode, within CopyFormatOptions. This approach, while functional, isn't ideal for future expansion. To simplify adding new formats, we've introduced an enum CopyFormat. This makes the code cleaner and more maintainable, allowing for easier integration of additional formats down the line. The CopyFormat enum was originally contributed by Joel Jacobson [email protected], later refactored by Jian He to address various issues. discussion: https://postgr.es/m/CALvfUkBxTYy5uWPFVwpk_7ii2zgT07t3d-yR_cy4sfrrLU%3Dkcg%40mail.gmail.com discussion: https://postgr.es/m/[email protected]
1 parent acbc9be commit 1468ecb

File tree

6 files changed

+49
-36
lines changed

6 files changed

+49
-36
lines changed

src/backend/commands/copy.c

Lines changed: 26 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,8 @@ ProcessCopyOptions(ParseState *pstate,
564564
opts_out = (CopyFormatOptions *) palloc0(sizeof(CopyFormatOptions));
565565

566566
opts_out->file_encoding = -1;
567+
/* default format */
568+
opts_out->format = COPY_FORMAT_TEXT;
567569

568570
/* Extract options from the statement node tree */
569571
foreach(option, options)
@@ -578,11 +580,11 @@ ProcessCopyOptions(ParseState *pstate,
578580
errorConflictingDefElem(defel, pstate);
579581
format_specified = true;
580582
if (strcmp(fmt, "text") == 0)
581-
/* default format */ ;
583+
opts_out->format = COPY_FORMAT_TEXT;
582584
else if (strcmp(fmt, "csv") == 0)
583-
opts_out->csv_mode = true;
585+
opts_out->format = COPY_FORMAT_CSV;
584586
else if (strcmp(fmt, "binary") == 0)
585-
opts_out->binary = true;
587+
opts_out->format = COPY_FORMAT_BINARY;
586588
else
587589
ereport(ERROR,
588590
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -742,31 +744,31 @@ ProcessCopyOptions(ParseState *pstate,
742744
* Check for incompatible options (must do these three before inserting
743745
* defaults)
744746
*/
745-
if (opts_out->binary && opts_out->delim)
747+
if (opts_out->format == COPY_FORMAT_BINARY && opts_out->delim)
746748
ereport(ERROR,
747749
(errcode(ERRCODE_SYNTAX_ERROR),
748750
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
749751
errmsg("cannot specify %s in BINARY mode", "DELIMITER")));
750752

751-
if (opts_out->binary && opts_out->null_print)
753+
if (opts_out->format == COPY_FORMAT_BINARY && opts_out->null_print)
752754
ereport(ERROR,
753755
(errcode(ERRCODE_SYNTAX_ERROR),
754756
errmsg("cannot specify %s in BINARY mode", "NULL")));
755757

756-
if (opts_out->binary && opts_out->default_print)
758+
if (opts_out->format == COPY_FORMAT_BINARY && opts_out->default_print)
757759
ereport(ERROR,
758760
(errcode(ERRCODE_SYNTAX_ERROR),
759761
errmsg("cannot specify %s in BINARY mode", "DEFAULT")));
760762

761763
/* Set defaults for omitted options */
762764
if (!opts_out->delim)
763-
opts_out->delim = opts_out->csv_mode ? "," : "\t";
765+
opts_out->delim = (opts_out->format == COPY_FORMAT_CSV) ? "," : "\t";
764766

765767
if (!opts_out->null_print)
766-
opts_out->null_print = opts_out->csv_mode ? "" : "\\N";
768+
opts_out->null_print = (opts_out->format == COPY_FORMAT_CSV) ? "" : "\\N";
767769
opts_out->null_print_len = strlen(opts_out->null_print);
768770

769-
if (opts_out->csv_mode)
771+
if (opts_out->format == COPY_FORMAT_CSV)
770772
{
771773
if (!opts_out->quote)
772774
opts_out->quote = "\"";
@@ -814,51 +816,51 @@ ProcessCopyOptions(ParseState *pstate,
814816
* future-proofing. Likewise we disallow all digits though only octal
815817
* digits are actually dangerous.
816818
*/
817-
if (!opts_out->csv_mode &&
819+
if (opts_out->format != COPY_FORMAT_CSV &&
818820
strchr("\\.abcdefghijklmnopqrstuvwxyz0123456789",
819821
opts_out->delim[0]) != NULL)
820822
ereport(ERROR,
821823
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
822824
errmsg("COPY delimiter cannot be \"%s\"", opts_out->delim)));
823825

824826
/* Check header */
825-
if (opts_out->binary && opts_out->header_line != COPY_HEADER_FALSE)
827+
if (opts_out->format == COPY_FORMAT_BINARY && opts_out->header_line != COPY_HEADER_FALSE)
826828
ereport(ERROR,
827829
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
828830
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
829831
errmsg("cannot specify %s in BINARY mode", "HEADER")));
830832

831833
/* Check quote */
832-
if (!opts_out->csv_mode && opts_out->quote != NULL)
834+
if (opts_out->format != COPY_FORMAT_CSV && opts_out->quote != NULL)
833835
ereport(ERROR,
834836
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
835837
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
836838
errmsg("COPY %s requires CSV mode", "QUOTE")));
837839

838-
if (opts_out->csv_mode && strlen(opts_out->quote) != 1)
840+
if (opts_out->format == COPY_FORMAT_CSV && strlen(opts_out->quote) != 1)
839841
ereport(ERROR,
840842
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
841843
errmsg("COPY quote must be a single one-byte character")));
842844

843-
if (opts_out->csv_mode && opts_out->delim[0] == opts_out->quote[0])
845+
if (opts_out->format == COPY_FORMAT_CSV && opts_out->delim[0] == opts_out->quote[0])
844846
ereport(ERROR,
845847
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
846848
errmsg("COPY delimiter and quote must be different")));
847849

848850
/* Check escape */
849-
if (!opts_out->csv_mode && opts_out->escape != NULL)
851+
if (opts_out->format != COPY_FORMAT_CSV && opts_out->escape != NULL)
850852
ereport(ERROR,
851853
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
852854
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
853855
errmsg("COPY %s requires CSV mode", "ESCAPE")));
854856

855-
if (opts_out->csv_mode && strlen(opts_out->escape) != 1)
857+
if (opts_out->format == COPY_FORMAT_CSV && strlen(opts_out->escape) != 1)
856858
ereport(ERROR,
857859
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
858860
errmsg("COPY escape must be a single one-byte character")));
859861

860862
/* Check force_quote */
861-
if (!opts_out->csv_mode && (opts_out->force_quote || opts_out->force_quote_all))
863+
if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_quote || opts_out->force_quote_all))
862864
ereport(ERROR,
863865
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
864866
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
@@ -872,8 +874,8 @@ ProcessCopyOptions(ParseState *pstate,
872874
"COPY FROM")));
873875

874876
/* Check force_notnull */
875-
if (!opts_out->csv_mode && (opts_out->force_notnull != NIL ||
876-
opts_out->force_notnull_all))
877+
if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_notnull != NIL ||
878+
opts_out->force_notnull_all))
877879
ereport(ERROR,
878880
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
879881
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
@@ -888,8 +890,8 @@ ProcessCopyOptions(ParseState *pstate,
888890
"COPY TO")));
889891

890892
/* Check force_null */
891-
if (!opts_out->csv_mode && (opts_out->force_null != NIL ||
892-
opts_out->force_null_all))
893+
if (opts_out->format != COPY_FORMAT_CSV && (opts_out->force_null != NIL ||
894+
opts_out->force_null_all))
893895
ereport(ERROR,
894896
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
895897
/*- translator: %s is the name of a COPY option, e.g. ON_ERROR */
@@ -913,7 +915,7 @@ ProcessCopyOptions(ParseState *pstate,
913915
"NULL")));
914916

915917
/* Don't allow the CSV quote char to appear in the null string. */
916-
if (opts_out->csv_mode &&
918+
if (opts_out->format == COPY_FORMAT_CSV &&
917919
strchr(opts_out->null_print, opts_out->quote[0]) != NULL)
918920
ereport(ERROR,
919921
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
@@ -949,7 +951,7 @@ ProcessCopyOptions(ParseState *pstate,
949951
"DEFAULT")));
950952

951953
/* Don't allow the CSV quote char to appear in the default string. */
952-
if (opts_out->csv_mode &&
954+
if (opts_out->format == COPY_FORMAT_CSV &&
953955
strchr(opts_out->default_print, opts_out->quote[0]) != NULL)
954956
ereport(ERROR,
955957
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -966,7 +968,7 @@ ProcessCopyOptions(ParseState *pstate,
966968
errmsg("NULL specification and DEFAULT specification cannot be the same")));
967969
}
968970
/* Check on_error */
969-
if (opts_out->binary && opts_out->on_error != COPY_ON_ERROR_STOP)
971+
if (opts_out->format == COPY_FORMAT_BINARY && opts_out->on_error != COPY_ON_ERROR_STOP)
970972
ereport(ERROR,
971973
(errcode(ERRCODE_SYNTAX_ERROR),
972974
errmsg("only ON_ERROR STOP is allowed in BINARY mode")));

src/backend/commands/copyfrom.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,9 +155,9 @@ static const CopyFromRoutine CopyFromRoutineBinary = {
155155
static const CopyFromRoutine *
156156
CopyFromGetRoutine(const CopyFormatOptions *opts)
157157
{
158-
if (opts->csv_mode)
158+
if (opts->format == COPY_FORMAT_CSV)
159159
return &CopyFromRoutineCSV;
160-
else if (opts->binary)
160+
else if (opts->format == COPY_FORMAT_BINARY)
161161
return &CopyFromRoutineBinary;
162162

163163
/* default is text */
@@ -261,7 +261,7 @@ CopyFromErrorCallback(void *arg)
261261
cstate->cur_relname);
262262
return;
263263
}
264-
if (cstate->opts.binary)
264+
if (cstate->opts.format == COPY_FORMAT_BINARY)
265265
{
266266
/* can't usefully display the data */
267267
if (cstate->cur_attname)

src/backend/commands/copyfromparse.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ ReceiveCopyBegin(CopyFromState cstate)
171171
{
172172
StringInfoData buf;
173173
int natts = list_length(cstate->attnumlist);
174-
int16 format = (cstate->opts.binary ? 1 : 0);
174+
int16 format = (cstate->opts.format == COPY_FORMAT_BINARY ? 1 : 0);
175175
int i;
176176

177177
pq_beginmessage(&buf, PqMsg_CopyInResponse);
@@ -747,7 +747,7 @@ bool
747747
NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
748748
{
749749
return NextCopyFromRawFieldsInternal(cstate, fields, nfields,
750-
cstate->opts.csv_mode);
750+
cstate->opts.format == COPY_FORMAT_CSV);
751751
}
752752

753753
/*
@@ -774,7 +774,8 @@ NextCopyFromRawFieldsInternal(CopyFromState cstate, char ***fields, int *nfields
774774
bool done = false;
775775

776776
/* only available for text or csv input */
777-
Assert(!cstate->opts.binary);
777+
Assert(cstate->opts.format == COPY_FORMAT_TEXT ||
778+
cstate->opts.format == COPY_FORMAT_CSV);
778779

779780
/* on input check that the header line is correct if needed */
780781
if (cstate->cur_lineno == 0 && cstate->opts.header_line != COPY_HEADER_FALSE)

src/backend/commands/copyto.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -181,9 +181,9 @@ static const CopyToRoutine CopyToRoutineBinary = {
181181
static const CopyToRoutine *
182182
CopyToGetRoutine(const CopyFormatOptions *opts)
183183
{
184-
if (opts->csv_mode)
184+
if (opts->format == COPY_FORMAT_CSV)
185185
return &CopyToRoutineCSV;
186-
else if (opts->binary)
186+
else if (opts->format == COPY_FORMAT_BINARY)
187187
return &CopyToRoutineBinary;
188188

189189
/* default is text */
@@ -220,7 +220,7 @@ CopyToTextLikeStart(CopyToState cstate, TupleDesc tupDesc)
220220

221221
colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
222222

223-
if (cstate->opts.csv_mode)
223+
if (cstate->opts.format == COPY_FORMAT_CSV)
224224
CopyAttributeOutCSV(cstate, colname, false);
225225
else
226226
CopyAttributeOutText(cstate, colname);
@@ -397,7 +397,7 @@ SendCopyBegin(CopyToState cstate)
397397
{
398398
StringInfoData buf;
399399
int natts = list_length(cstate->attnumlist);
400-
int16 format = (cstate->opts.binary ? 1 : 0);
400+
int16 format = (cstate->opts.format == COPY_FORMAT_BINARY ? 1 : 0);
401401
int i;
402402

403403
pq_beginmessage(&buf, PqMsg_CopyOutResponse);

src/include/commands/copy.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ typedef enum CopyLogVerbosityChoice
4848
COPY_LOG_VERBOSITY_VERBOSE, /* logs additional messages */
4949
} CopyLogVerbosityChoice;
5050

51+
/*
52+
* Represents the format of the COPY operation.
53+
*/
54+
typedef enum CopyFormat
55+
{
56+
COPY_FORMAT_TEXT = 0,
57+
COPY_FORMAT_BINARY,
58+
COPY_FORMAT_CSV,
59+
} CopyFormat;
60+
5161
/*
5262
* A struct to hold COPY options, in a parsed form. All of these are related
5363
* to formatting, except for 'freeze', which doesn't really belong here, but
@@ -58,9 +68,8 @@ typedef struct CopyFormatOptions
5868
/* parameters from the COPY command */
5969
int file_encoding; /* file or remote side's character encoding,
6070
* -1 if not specified */
61-
bool binary; /* binary format? */
71+
CopyFormat format; /* format of the COPY operation */
6272
bool freeze; /* freeze rows on loading? */
63-
bool csv_mode; /* Comma Separated Value format? */
6473
int header_line; /* number of lines to skip or COPY_HEADER_XXX
6574
* value (see the above) */
6675
char *null_print; /* NULL marker string (server encoding!) */

src/tools/pgindent/typedefs.list

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -516,6 +516,7 @@ ConversionLocation
516516
ConvertRowtypeExpr
517517
CookedConstraint
518518
CopyDest
519+
CopyFormat
519520
CopyFormatOptions
520521
CopyFromRoutine
521522
CopyFromState

0 commit comments

Comments
 (0)