@@ -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 )
0 commit comments