@@ -95,8 +95,8 @@ typedef struct CopyStateData
9595 * dest == COPY_NEW_FE in COPY FROM */
9696bool fe_eof ;/* true if detected end of copy data */
9797EolType eol_type ;/* EOL type of input */
98- int client_encoding ;/* remote side's character encoding */
99- bool need_transcoding ;/*client encoding diff from server? */
98+ int file_encoding ;/* file or remote side's character encoding */
99+ bool need_transcoding ;/*file encoding diff from server? */
100100bool encoding_embeds_ascii ;/* ASCII can be non-first byte? */
101101
102102/* parameters from the COPY command */
@@ -110,7 +110,7 @@ typedef struct CopyStateData
110110bool header_line ;/* CSV header line? */
111111char * null_print ;/* NULL marker string (server encoding!) */
112112int null_print_len ;/* length of same */
113- char * null_print_client ;/* same converted toclient encoding */
113+ char * null_print_client ;/* same converted tofile encoding */
114114char * delim ;/* column delimiter (must be 1 byte) */
115115char * quote ;/* CSV quote char (must be 1 byte) */
116116char * escape ;/* CSV escape char (must be 1 byte) */
@@ -845,6 +845,8 @@ ProcessCopyOptions(CopyState cstate,
845845if (cstate == NULL )
846846cstate = (CopyStateData * )palloc0 (sizeof (CopyStateData ));
847847
848+ cstate -> file_encoding = -1 ;
849+
848850/* Extract options from the statement node tree */
849851foreach (option ,options )
850852{
@@ -948,6 +950,19 @@ ProcessCopyOptions(CopyState cstate,
948950errmsg ("argument to option \"%s\" must be a list of column names" ,
949951defel -> defname )));
950952}
953+ else if (strcmp (defel -> defname ,"encoding" )== 0 )
954+ {
955+ if (cstate -> file_encoding >=0 )
956+ ereport (ERROR ,
957+ (errcode (ERRCODE_SYNTAX_ERROR ),
958+ errmsg ("conflicting or redundant options" )));
959+ cstate -> file_encoding = pg_char_to_encoding (defGetString (defel ));
960+ if (cstate -> file_encoding < 0 )
961+ ereport (ERROR ,
962+ (errcode (ERRCODE_INVALID_PARAMETER_VALUE ),
963+ errmsg ("argument to option \"%s\" must be a valid encoding name" ,
964+ defel -> defname )));
965+ }
951966else
952967ereport (ERROR ,
953968(errcode (ERRCODE_SYNTAX_ERROR ),
@@ -1278,17 +1293,20 @@ BeginCopy(bool is_from,
12781293}
12791294}
12801295
1296+ /* Use client encoding when ENCODING option is not specified. */
1297+ if (cstate -> file_encoding < 0 )
1298+ cstate -> file_encoding = pg_get_client_encoding ();
1299+
12811300/*
1282- * Set up encoding conversion info. Even if theclient and server
1283- * encodings are the same, we must applypg_client_to_server () to validate
1301+ * Set up encoding conversion info. Even if thefile and server
1302+ * encodings are the same, we must applypg_any_to_server () to validate
12841303 * data in multibyte encodings.
12851304 */
1286- cstate -> client_encoding = pg_get_client_encoding ();
12871305cstate -> need_transcoding =
1288- (cstate -> client_encoding != GetDatabaseEncoding ()||
1306+ (cstate -> file_encoding != GetDatabaseEncoding ()||
12891307pg_database_encoding_max_length ()> 1 );
12901308/* See Multibyte encoding comment above */
1291- cstate -> encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY (cstate -> client_encoding );
1309+ cstate -> encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY (cstate -> file_encoding );
12921310
12931311cstate -> copy_dest = COPY_FILE ;/* default */
12941312
@@ -1526,12 +1544,13 @@ CopyTo(CopyState cstate)
15261544else
15271545{
15281546/*
1529- * For non-binary copy, we need to convert null_print toclient
1547+ * For non-binary copy, we need to convert null_print tofile
15301548 * encoding, because it will be sent directly with CopySendString.
15311549 */
15321550if (cstate -> need_transcoding )
1533- cstate -> null_print_client = pg_server_to_client (cstate -> null_print ,
1534- cstate -> null_print_len );
1551+ cstate -> null_print_client = pg_server_to_any (cstate -> null_print ,
1552+ cstate -> null_print_len ,
1553+ cstate -> file_encoding );
15351554
15361555/* if a header has been requested send the line */
15371556if (cstate -> header_line )
@@ -2608,8 +2627,9 @@ CopyReadLine(CopyState cstate)
26082627{
26092628char * cvt ;
26102629
2611- cvt = pg_client_to_server (cstate -> line_buf .data ,
2612- cstate -> line_buf .len );
2630+ cvt = pg_any_to_server (cstate -> line_buf .data ,
2631+ cstate -> line_buf .len ,
2632+ cstate -> file_encoding );
26132633if (cvt != cstate -> line_buf .data )
26142634{
26152635/* transfer converted data back to line_buf */
@@ -2854,7 +2874,7 @@ CopyReadLineText(CopyState cstate)
28542874/* -----
28552875 * get next character
28562876 * Note: we do not change c so if it isn't \., we can fall
2857- * through and continue processing forclient encoding.
2877+ * through and continue processing forfile encoding.
28582878 * -----
28592879 */
28602880c2 = copy_raw_buf [raw_buf_ptr ];
@@ -2968,7 +2988,7 @@ CopyReadLineText(CopyState cstate)
29682988
29692989mblen_str [0 ]= c ;
29702990/* All our encodings only read the first byte to get the length */
2971- mblen = pg_encoding_mblen (cstate -> client_encoding ,mblen_str );
2991+ mblen = pg_encoding_mblen (cstate -> file_encoding ,mblen_str );
29722992IF_NEED_REFILL_AND_NOT_EOF_CONTINUE (mblen - 1 );
29732993IF_NEED_REFILL_AND_EOF_BREAK (mblen - 1 );
29742994raw_buf_ptr += mblen - 1 ;
@@ -3467,7 +3487,7 @@ CopyAttributeOutText(CopyState cstate, char *string)
34673487char delimc = cstate -> delim [0 ];
34683488
34693489if (cstate -> need_transcoding )
3470- ptr = pg_server_to_client (string ,strlen (string ));
3490+ ptr = pg_server_to_any (string ,strlen (string ), cstate -> file_encoding );
34713491else
34723492ptr = string ;
34733493
@@ -3540,7 +3560,7 @@ CopyAttributeOutText(CopyState cstate, char *string)
35403560start = ptr ++ ;/* we include char in next run */
35413561}
35423562else if (IS_HIGHBIT_SET (c ))
3543- ptr += pg_encoding_mblen (cstate -> client_encoding ,ptr );
3563+ ptr += pg_encoding_mblen (cstate -> file_encoding ,ptr );
35443564else
35453565ptr ++ ;
35463566}
@@ -3627,7 +3647,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36273647use_quote = true;
36283648
36293649if (cstate -> need_transcoding )
3630- ptr = pg_server_to_client (string ,strlen (string ));
3650+ ptr = pg_server_to_any (string ,strlen (string ), cstate -> file_encoding );
36313651else
36323652ptr = string ;
36333653
@@ -3654,7 +3674,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36543674break ;
36553675}
36563676if (IS_HIGHBIT_SET (c )&& cstate -> encoding_embeds_ascii )
3657- tptr += pg_encoding_mblen (cstate -> client_encoding ,tptr );
3677+ tptr += pg_encoding_mblen (cstate -> file_encoding ,tptr );
36583678else
36593679tptr ++ ;
36603680}
@@ -3678,7 +3698,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36783698start = ptr ;/* we include char in next run */
36793699}
36803700if (IS_HIGHBIT_SET (c )&& cstate -> encoding_embeds_ascii )
3681- ptr += pg_encoding_mblen (cstate -> client_encoding ,ptr );
3701+ ptr += pg_encoding_mblen (cstate -> file_encoding ,ptr );
36823702else
36833703ptr ++ ;
36843704}