@@ -95,8 +95,8 @@ typedef struct CopyStateData
9595 * dest == COPY_NEW_FE in COPY FROM */
9696 bool fe_eof ; /* true if detected end of copy data */
9797 EolType 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? */
100100 bool encoding_embeds_ascii ; /* ASCII can be non-first byte? */
101101
102102 /* parameters from the COPY command */
@@ -110,7 +110,7 @@ typedef struct CopyStateData
110110 bool header_line ; /* CSV header line? */
111111 char * null_print ; /* NULL marker string (server encoding!) */
112112 int null_print_len ; /* length of same */
113- char * null_print_client ; /* same converted to client encoding */
113+ char * null_print_client ; /* same converted to file encoding */
114114 char * delim ; /* column delimiter (must be 1 byte) */
115115 char * quote ; /* CSV quote char (must be 1 byte) */
116116 char * escape ; /* CSV escape char (must be 1 byte) */
@@ -845,6 +845,8 @@ ProcessCopyOptions(CopyState cstate,
845845 if (cstate == NULL )
846846 cstate = (CopyStateData * ) palloc0 (sizeof (CopyStateData ));
847847
848+ cstate -> file_encoding = -1 ;
849+
848850 /* Extract options from the statement node tree */
849851 foreach (option , options )
850852 {
@@ -948,6 +950,19 @@ ProcessCopyOptions(CopyState cstate,
948950 errmsg ("argument to option \"%s\" must be a list of column names" ,
949951 defel -> 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+ }
951966 else
952967 ereport (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 the client and server
1283- * encodings are the same, we must apply pg_client_to_server () to validate
1301+ * Set up encoding conversion info. Even if the file and server
1302+ * encodings are the same, we must apply pg_any_to_server () to validate
12841303 * data in multibyte encodings.
12851304 */
1286- cstate -> client_encoding = pg_get_client_encoding ();
12871305 cstate -> need_transcoding =
1288- (cstate -> client_encoding != GetDatabaseEncoding () ||
1306+ (cstate -> file_encoding != GetDatabaseEncoding () ||
12891307 pg_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
12931311 cstate -> copy_dest = COPY_FILE ; /* default */
12941312
@@ -1526,12 +1544,13 @@ CopyTo(CopyState cstate)
15261544 else
15271545 {
15281546 /*
1529- * For non-binary copy, we need to convert null_print to client
1547+ * For non-binary copy, we need to convert null_print to file
15301548 * encoding, because it will be sent directly with CopySendString.
15311549 */
15321550 if (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 */
15371556 if (cstate -> header_line )
@@ -2608,8 +2627,9 @@ CopyReadLine(CopyState cstate)
26082627 {
26092628 char * 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 );
26132633 if (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 for client encoding.
2877+ * through and continue processing for file encoding.
28582878 * -----
28592879 */
28602880 c2 = copy_raw_buf [raw_buf_ptr ];
@@ -2968,7 +2988,7 @@ CopyReadLineText(CopyState cstate)
29682988
29692989 mblen_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 );
29722992 IF_NEED_REFILL_AND_NOT_EOF_CONTINUE (mblen - 1 );
29732993 IF_NEED_REFILL_AND_EOF_BREAK (mblen - 1 );
29742994 raw_buf_ptr += mblen - 1 ;
@@ -3467,7 +3487,7 @@ CopyAttributeOutText(CopyState cstate, char *string)
34673487 char delimc = cstate -> delim [0 ];
34683488
34693489 if (cstate -> need_transcoding )
3470- ptr = pg_server_to_client (string , strlen (string ));
3490+ ptr = pg_server_to_any (string , strlen (string ), cstate -> file_encoding );
34713491 else
34723492 ptr = string ;
34733493
@@ -3540,7 +3560,7 @@ CopyAttributeOutText(CopyState cstate, char *string)
35403560 start = ptr ++ ; /* we include char in next run */
35413561 }
35423562 else if (IS_HIGHBIT_SET (c ))
3543- ptr += pg_encoding_mblen (cstate -> client_encoding , ptr );
3563+ ptr += pg_encoding_mblen (cstate -> file_encoding , ptr );
35443564 else
35453565 ptr ++ ;
35463566 }
@@ -3627,7 +3647,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36273647 use_quote = true;
36283648
36293649 if (cstate -> need_transcoding )
3630- ptr = pg_server_to_client (string , strlen (string ));
3650+ ptr = pg_server_to_any (string , strlen (string ), cstate -> file_encoding );
36313651 else
36323652 ptr = string ;
36333653
@@ -3654,7 +3674,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36543674 break ;
36553675 }
36563676 if (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 );
36583678 else
36593679 tptr ++ ;
36603680 }
@@ -3678,7 +3698,7 @@ CopyAttributeOutCSV(CopyState cstate, char *string,
36783698 start = ptr ; /* we include char in next run */
36793699 }
36803700 if (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 );
36823702 else
36833703 ptr ++ ;
36843704 }
0 commit comments