diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c index 1fe70b9133..41f6bc43e4 100644 --- a/src/backend/commands/copyfrom.c +++ b/src/backend/commands/copyfrom.c @@ -1776,6 +1776,11 @@ BeginCopyFrom(ParseState *pstate, cstate->max_fields = attr_count; cstate->raw_fields = (char **) palloc(attr_count * sizeof(char *)); + + if (cstate->opts.csv_mode) + cstate->copy_read_attributes = CopyReadAttributesCSV; + else + cstate->copy_read_attributes = CopyReadAttributesText; } MemoryContextSwitchTo(oldcontext); diff --git a/src/backend/commands/copyfromparse.c b/src/backend/commands/copyfromparse.c index 7cacd0b752..906756362e 100644 --- a/src/backend/commands/copyfromparse.c +++ b/src/backend/commands/copyfromparse.c @@ -25,10 +25,10 @@ * is copied into 'line_buf', with quotes and escape characters still * intact. * - * 4. CopyReadAttributesText/CSV() function takes the input line from - * 'line_buf', and splits it into fields, unescaping the data as required. - * The fields are stored in 'attribute_buf', and 'raw_fields' array holds - * pointers to each field. + * 4. CopyReadAttributesText/CSV() function (via copy_read_attribute) takes + * the input line from 'line_buf', and splits it into fields, unescaping + * the data as required. The fields are stored in 'attribute_buf', and + * 'raw_fields' array holds pointers to each field. * * If encoding conversion is not required, a shortcut is taken in step 2 to * 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"; /* non-export function prototypes */ static bool CopyReadLine(CopyFromState cstate); static bool CopyReadLineText(CopyFromState cstate); -static int CopyReadAttributesText(CopyFromState cstate); -static int CopyReadAttributesCSV(CopyFromState cstate); static Datum CopyReadBinaryAttribute(CopyFromState cstate, FmgrInfo *flinfo, Oid typioparam, int32 typmod, bool *isnull); @@ -775,10 +773,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) { int fldnum; - if (cstate->opts.csv_mode) - fldct = CopyReadAttributesCSV(cstate); - else - fldct = CopyReadAttributesText(cstate); + fldct = cstate->copy_read_attributes(cstate); if (fldct != list_length(cstate->attnumlist)) ereport(ERROR, @@ -830,10 +825,7 @@ NextCopyFromRawFields(CopyFromState cstate, char ***fields, int *nfields) return false; /* Parse the line into de-escaped field values */ - if (cstate->opts.csv_mode) - fldct = CopyReadAttributesCSV(cstate); - else - fldct = CopyReadAttributesText(cstate); + fldct = cstate->copy_read_attributes(cstate); *fields = cstate->raw_fields; *nfields = fldct; @@ -1502,7 +1494,7 @@ GetDecimalFromHex(char hex) * * The return value is the number of fields actually read. */ -static int +int CopyReadAttributesText(CopyFromState cstate) { char delimc = cstate->opts.delim[0]; @@ -1756,7 +1748,7 @@ CopyReadAttributesText(CopyFromState cstate) * CopyReadAttributesText, except we parse the fields according to * "standard" (i.e. common) CSV usage. */ -static int +int CopyReadAttributesCSV(CopyFromState cstate) { char delimc = cstate->opts.delim[0]; diff --git a/src/include/commands/copyfrom_internal.h b/src/include/commands/copyfrom_internal.h index cad52fcc78..759f8e3d09 100644 --- a/src/include/commands/copyfrom_internal.h +++ b/src/include/commands/copyfrom_internal.h @@ -52,6 +52,13 @@ typedef enum CopyInsertMethod * ExecForeignBatchInsert only if valid */ } CopyInsertMethod; +/* + * Per-format callback to parse a line into separate fields. + * + * Returns the number of fields read. + */ +typedef int (*CopyReadAttributes) (CopyFromState cstate); + /* * This struct contains all the state variables used throughout a COPY FROM * operation. @@ -130,6 +137,12 @@ typedef struct CopyFromStateData int max_fields; char **raw_fields; + /* + * Per-format callback to parse lines, then fill raw_fields and + * attribute_buf. + */ + CopyReadAttributes copy_read_attributes; + /* * Similarly, line_buf holds the whole input line being processed. The * input cycle is first to read the whole line into line_buf, and then @@ -183,4 +196,8 @@ typedef struct CopyFromStateData extern void ReceiveCopyBegin(CopyFromState cstate); extern void ReceiveCopyBinaryHeader(CopyFromState cstate); +/* Callbacks for copy_read_attributes */ +extern int CopyReadAttributesCSV(CopyFromState cstate); +extern int CopyReadAttributesText(CopyFromState cstate); + #endif /* COPYFROM_INTERNAL_H */