Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 95fb5b4

Browse files
committed
Refactor CopyReadAttributes{CSV,Text}() to use a callback in COPY FROM
CopyReadAttributes{CSV,Text}() are used to parse lines for text and CSV format. This reduces the number of "if" branches that need to be checked when parsing fields in CSV and text mode when dealing with a COPY FROM, something that can become more noticeable with more attributes and more lines to process. Extracted from a larger patch by the same author. Author: Sutou Kouhei Discussion: https://postgr.es/m/20231204.153548.2126325458835528809.kou@clear-code.com
1 parent 774bcff commit 95fb5b4

File tree

3 files changed

+30
-16
lines changed

3 files changed

+30
-16
lines changed

src/backend/commands/copyfrom.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,6 +1776,11 @@ BeginCopyFrom(ParseState *pstate,
17761776

17771777
cstate->max_fields = attr_count;
17781778
cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *));
1779+
1780+
if (cstate->opts.csv_mode)
1781+
cstate->copy_read_attributes = CopyReadAttributesCSV;
1782+
else
1783+
cstate->copy_read_attributes = CopyReadAttributesText;
17791784
}
17801785

17811786
MemoryContextSwitchTo(oldcontext);

src/backend/commands/copyfromparse.c

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
* is copied into 'line_buf', with quotes and escape characters still
2626
* intact.
2727
*
28-
* 4. CopyReadAttributesText/CSV() function takes the input line from
29-
* 'line_buf', and splits it into fields, unescaping the data as required.
30-
* The fields are stored in 'attribute_buf', and 'raw_fields' array holds
31-
* pointers to each field.
28+
* 4. CopyReadAttributesText/CSV() function (via copy_read_attribute) takes
29+
* the input line from 'line_buf', and splits it into fields, unescaping
30+
* the data as required. The fields are stored in 'attribute_buf', and
31+
* 'raw_fields' array holds pointers to each field.
3232
*
3333
* If encoding conversion is not required, a shortcut is taken in step 2 to
3434
* avoid copying the data unnecessarily. The 'input_buf' pointer is set to
@@ -152,8 +152,6 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
152152
/* non-export function prototypes */
153153
static bool CopyReadLine(CopyFromState cstate);
154154
static bool CopyReadLineText(CopyFromState cstate);
155-
static int CopyReadAttributesText(CopyFromState cstate);
156-
static int CopyReadAttributesCSV(CopyFromState cstate);
157155
static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo,
158156
Oid typioparam, int32 typmod,
159157
bool *isnull);
@@ -775,10 +773,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
775773
{
776774
int fldnum;
777775

778-
if (cstate->opts.csv_mode)
779-
fldct = CopyReadAttributesCSV(cstate);
780-
else
781-
fldct = CopyReadAttributesText(cstate);
776+
fldct = cstate->copy_read_attributes(cstate);
782777

783778
if (fldct != list_length(cstate->attnumlist))
784779
ereport(ERROR,
@@ -830,10 +825,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields)
830825
return false;
831826

832827
/* Parse the line into de-escaped field values */
833-
if (cstate->opts.csv_mode)
834-
fldct = CopyReadAttributesCSV(cstate);
835-
else
836-
fldct = CopyReadAttributesText(cstate);
828+
fldct = cstate->copy_read_attributes(cstate);
837829

838830
*fields = cstate->raw_fields;
839831
*nfields = fldct;
@@ -1502,7 +1494,7 @@ GetDecimalFromHex(char hex)
15021494
*
15031495
* The return value is the number of fields actually read.
15041496
*/
1505-
static int
1497+
int
15061498
CopyReadAttributesText(CopyFromState cstate)
15071499
{
15081500
char delimc = cstate->opts.delim[0];
@@ -1756,7 +1748,7 @@ CopyReadAttributesText(CopyFromState cstate)
17561748
* CopyReadAttributesText, except we parse the fields according to
17571749
* "standard" (i.e. common) CSV usage.
17581750
*/
1759-
static int
1751+
int
17601752
CopyReadAttributesCSV(CopyFromState cstate)
17611753
{
17621754
char delimc = cstate->opts.delim[0];

src/include/commands/copyfrom_internal.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ typedef enum CopyInsertMethod
5252
* ExecForeignBatchInsert only if valid */
5353
} CopyInsertMethod;
5454

55+
/*
56+
* Per-format callback to parse a line into separate fields.
57+
*
58+
* Returns the number of fields read.
59+
*/
60+
typedef int (*CopyReadAttributes) (CopyFromState cstate);
61+
5562
/*
5663
* This struct contains all the state variables used throughout a COPY FROM
5764
* operation.
@@ -130,6 +137,12 @@ typedef struct CopyFromStateData
130137
int max_fields;
131138
char **raw_fields;
132139

140+
/*
141+
* Per-format callback to parse lines, then fill raw_fields and
142+
* attribute_buf.
143+
*/
144+
CopyReadAttributes copy_read_attributes;
145+
133146
/*
134147
* Similarly, line_buf holds the whole input line being processed. The
135148
* input cycle is first to read the whole line into line_buf, and then
@@ -183,4 +196,8 @@ typedef struct CopyFromStateData
183196
extern void ReceiveCopyBegin(CopyFromState cstate);
184197
extern void ReceiveCopyBinaryHeader(CopyFromState cstate);
185198

199+
/* Callbacks for copy_read_attributes */
200+
extern int CopyReadAttributesCSV(CopyFromState cstate);
201+
extern int CopyReadAttributesText(CopyFromState cstate);
202+
186203
#endif /* COPYFROM_INTERNAL_H */

0 commit comments

Comments
 (0)