summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Paquier2024-02-05 00:46:02 +0000
committerMichael Paquier2024-02-05 00:46:02 +0000
commit95fb5b49024aa51310f91aba669aaf0bb3227932 (patch)
tree7ccf2f1642c692fdbd45b864052fa257d9a40ee8
parent774bcffe4a9853a24e61d758637c0aad2871f1fb (diff)
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/[email protected]
-rw-r--r--src/backend/commands/copyfrom.c5
-rw-r--r--src/backend/commands/copyfromparse.c24
-rw-r--r--src/include/commands/copyfrom_internal.h17
3 files changed, 30 insertions, 16 deletions
diff --git a/src/backend/commands/copyfrom.c b/src/backend/commands/copyfrom.c
index 1fe70b91338..41f6bc43e49 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 7cacd0b752c..906756362e9 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 cad52fcc783..759f8e3d090 100644
--- a/src/include/commands/copyfrom_internal.h
+++ b/src/include/commands/copyfrom_internal.h
@@ -53,6 +53,13 @@ typedef enum CopyInsertMethod
} 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.
*/
@@ -131,6 +138,12 @@ typedef struct CopyFromStateData
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
* extract the individual attribute fields into attribute_buf. line_buf
@@ -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 */