@@ -54,6 +54,14 @@ typedef enum CopyDest
54
54
COPY_CALLBACK ,/* to callback function */
55
55
}CopyDest ;
56
56
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
+
57
65
/*
58
66
* This struct contains all the state variables used throughout a COPY TO
59
67
* operation.
@@ -97,6 +105,7 @@ typedef struct CopyToStateData
97
105
MemoryContext copycontext ;/* per-copy execution context */
98
106
99
107
FmgrInfo * out_functions ;/* lookup info for output functions */
108
+ CopyAttributeOut copy_attribute_out ;/* output representation callback */
100
109
MemoryContext rowcontext ;/* per-row evaluation context */
101
110
uint64 bytes_processed ;/* number of bytes processed so far */
102
111
}CopyToStateData ;
@@ -117,9 +126,12 @@ static const char BinarySignature[11] = "PGCOPY\n\377\r\n\0";
117
126
static void EndCopy (CopyToState cstate );
118
127
static void ClosePipeToProgram (CopyToState cstate );
119
128
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 );
121
133
static void CopyAttributeOutCSV (CopyToState cstate ,const char * string ,
122
- bool use_quote , bool single_attr );
134
+ bool use_quote );
123
135
124
136
/* Low-level communications functions */
125
137
static void SendCopyBegin (CopyToState cstate );
@@ -433,6 +445,15 @@ BeginCopyTo(ParseState *pstate,
433
445
/* Extract options from the statement node tree */
434
446
ProcessCopyOptions (pstate ,& cstate -> opts , false/* is_from */ ,options );
435
447
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
+
436
457
/* Process the source/target relation or query */
437
458
if (rel )
438
459
{
@@ -836,11 +857,8 @@ DoCopyTo(CopyToState cstate)
836
857
837
858
colname = NameStr (TupleDescAttr (tupDesc ,attnum - 1 )-> attname );
838
859
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);
844
862
}
845
863
846
864
CopySendEndOfRow (cstate );
@@ -950,12 +968,9 @@ CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
950
968
{
951
969
string = OutputFunctionCall (& out_functions [attnum - 1 ],
952
970
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 ]);
959
974
}
960
975
else
961
976
{
@@ -985,7 +1000,8 @@ CopyOneRowTo(CopyToState cstate, TupleTableSlot *slot)
985
1000
} while (0)
986
1001
987
1002
static void
988
- CopyAttributeOutText (CopyToState cstate ,const char * string )
1003
+ CopyAttributeOutText (CopyToState cstate ,const char * string ,
1004
+ bool use_quote )
989
1005
{
990
1006
const char * ptr ;
991
1007
const char * start ;
@@ -1139,14 +1155,15 @@ CopyAttributeOutText(CopyToState cstate, const char *string)
1139
1155
*/
1140
1156
static void
1141
1157
CopyAttributeOutCSV (CopyToState cstate ,const char * string ,
1142
- bool use_quote , bool single_attr )
1158
+ bool use_quote )
1143
1159
{
1144
1160
const char * ptr ;
1145
1161
const char * start ;
1146
1162
char c ;
1147
1163
char delimc = cstate -> opts .delim [0 ];
1148
1164
char quotec = cstate -> opts .quote [0 ];
1149
1165
char escapec = cstate -> opts .escape [0 ];
1166
+ bool single_attr = (list_length (cstate -> attnumlist )== 1 );
1150
1167
1151
1168
/* force quoting if it matches null_print (before conversion!) */
1152
1169
if (!use_quote && strcmp (string ,cstate -> opts .null_print )== 0 )