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

Commit 2889fd2

Browse files
committed
Refactor CopyAttributeOut{CSV,Text}() to use a callback in COPY TO
These routines are used by the text and CSV formats to send an output representation of a string, applying quotes if required. This is similar to 95fb5b4, reducing the number of "if" branches that need to be checked on a per-row basis when sending representation of fields in text or CSV mode. While on it, this simplifies the signature of CopyAttributeOutCSV() as it is possible to know that an attribute is alone on a line thanks to CopyToState. Headers should not use quotes, even if forced at query level. 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 95fb5b4 commit 2889fd2

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

src/backend/commands/copyto.c

+32-15
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,14 @@ typedef enum CopyDest
5454
COPY_CALLBACK, /* to callback function */
5555
} CopyDest;
5656

57+
/*
58+
* Per-format callback to send output representation of one attribute for
59+
* a `string`. `use_quote` tracks if quotes are required in the output
60+
* representation.
61+
*/
62+
typedef void (*CopyAttributeOut) (CopyToState cstate, const char *string,
63+
bool use_quote);
64+
5765
/*
5866
* This struct contains all the state variables used throughout a COPY TO
5967
* operation.
@@ -97,6 +105,7 @@ typedef struct CopyToStateData
97105
MemoryContext copycontext; /* per-copy execution context */
98106

99107
FmgrInfo *out_functions; /* lookup info for output functions */
108+
CopyAttributeOut copy_attribute_out; /* output representation callback */
100109
MemoryContext rowcontext; /* per-row evaluation context */
101110
uint64 bytes_processed; /* number of bytes processed so far */
102111
} CopyToStateData;
@@ -117,9 +126,12 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
117126
static void EndCopy(CopyToState cstate);
118127
static void ClosePipeToProgram(CopyToState cstate);
119128
static void CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot);
120-
static void CopyAttributeOutText(CopyToState cstate, const char *string);
129+
130+
/* Callbacks for copy_attribute_out */
131+
static void CopyAttributeOutText(CopyToState cstate, const char *string,
132+
bool use_quote);
121133
static void CopyAttributeOutCSV(CopyToState cstate, const char *string,
122-
bool use_quote, bool single_attr);
134+
bool use_quote);
123135

124136
/* Low-level communications functions */
125137
static void SendCopyBegin(CopyToState cstate);
@@ -433,6 +445,15 @@ BeginCopyTo(ParseState *pstate,
433445
/* Extract options from the statement node tree */
434446
ProcessCopyOptions(pstate, &cstate->opts, false /* is_from */ , options);
435447

448+
/* Set output representation callback */
449+
if (!cstate->opts.binary)
450+
{
451+
if (cstate->opts.csv_mode)
452+
cstate->copy_attribute_out = CopyAttributeOutCSV;
453+
else
454+
cstate->copy_attribute_out = CopyAttributeOutText;
455+
}
456+
436457
/* Process the source/target relation or query */
437458
if (rel)
438459
{
@@ -836,11 +857,8 @@ DoCopyTo(CopyToState cstate)
836857

837858
colname = NameStr(TupleDescAttr(tupDesc, attnum - 1)->attname);
838859

839-
if (cstate->opts.csv_mode)
840-
CopyAttributeOutCSV(cstate, colname, false,
841-
list_length(cstate->attnumlist) == 1);
842-
else
843-
CopyAttributeOutText(cstate, colname);
860+
/* Ignore quotes */
861+
cstate->copy_attribute_out(cstate, colname, false);
844862
}
845863

846864
CopySendEndOfRow(cstate);
@@ -950,12 +968,9 @@ CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
950968
{
951969
string = OutputFunctionCall(&out_functions[attnum - 1],
952970
value);
953-
if (cstate->opts.csv_mode)
954-
CopyAttributeOutCSV(cstate, string,
955-
cstate->opts.force_quote_flags[attnum - 1],
956-
list_length(cstate->attnumlist) == 1);
957-
else
958-
CopyAttributeOutText(cstate, string);
971+
972+
cstate->copy_attribute_out(cstate, string,
973+
cstate->opts.force_quote_flags[attnum - 1]);
959974
}
960975
else
961976
{
@@ -985,7 +1000,8 @@ CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
9851000
} while (0)
9861001

9871002
static void
988-
CopyAttributeOutText(CopyToState cstate, const char *string)
1003+
CopyAttributeOutText(CopyToState cstate, const char *string,
1004+
bool use_quote)
9891005
{
9901006
const char *ptr;
9911007
const char *start;
@@ -1139,14 +1155,15 @@ CopyAttributeOutText(CopyToState cstate, const char *string)
11391155
*/
11401156
static void
11411157
CopyAttributeOutCSV(CopyToState cstate, const char *string,
1142-
bool use_quote, bool single_attr)
1158+
bool use_quote)
11431159
{
11441160
const char *ptr;
11451161
const char *start;
11461162
char c;
11471163
char delimc = cstate->opts.delim[0];
11481164
char quotec = cstate->opts.quote[0];
11491165
char escapec = cstate->opts.escape[0];
1166+
bool single_attr = (list_length(cstate->attnumlist) == 1);
11501167

11511168
/* force quoting if it matches null_print (before conversion!) */
11521169
if (!use_quote && strcmp(string, cstate->opts.null_print) == 0)

0 commit comments

Comments
 (0)