8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.214 2003/11/29 19:51:47 pgsql Exp $
11
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.215 2004/01/18 02:15:29 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -139,6 +139,7 @@ static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
139
139
Oid typelem , bool * isnull );
140
140
static void CopyAttributeOut (char * string , char * delim );
141
141
static List * CopyGetAttnums (Relation rel , List * attnamelist );
142
+ static void limit_printout_length (StringInfo buf );
142
143
143
144
/* Internal communications functions */
144
145
static void SendCopyBegin (bool binary , int natts );
@@ -1140,8 +1141,6 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
1140
1141
static void
1141
1142
copy_in_error_callback (void * arg )
1142
1143
{
1143
- #define MAX_COPY_DATA_DISPLAY 100
1144
-
1145
1144
if (copy_binary )
1146
1145
{
1147
1146
/* can't usefully display the data */
@@ -1156,17 +1155,18 @@ copy_in_error_callback(void *arg)
1156
1155
if (copy_attname )
1157
1156
{
1158
1157
/* error is relevant to a particular column */
1159
- errcontext ("COPY %s, line %d, column %s: \"%.*s%s\"" ,
1158
+ limit_printout_length (& attribute_buf );
1159
+ errcontext ("COPY %s, line %d, column %s: \"%s\"" ,
1160
1160
copy_relname , copy_lineno , copy_attname ,
1161
- MAX_COPY_DATA_DISPLAY , attribute_buf .data ,
1162
- (attribute_buf .len > MAX_COPY_DATA_DISPLAY ) ? "..." : "" );
1161
+ attribute_buf .data );
1163
1162
}
1164
1163
else
1165
1164
{
1166
1165
/* error is relevant to a particular line */
1167
1166
if (!line_buf_converted )
1168
1167
{
1169
1168
/* didn't convert the encoding yet... */
1169
+ line_buf_converted = true;
1170
1170
if (client_encoding != server_encoding )
1171
1171
{
1172
1172
char * cvt ;
@@ -1181,16 +1181,46 @@ copy_in_error_callback(void *arg)
1181
1181
appendBinaryStringInfo (& line_buf , cvt , strlen (cvt ));
1182
1182
}
1183
1183
}
1184
- line_buf_converted = true;
1185
1184
}
1186
- errcontext ("COPY %s, line %d: \"%.*s%s\"" ,
1185
+ limit_printout_length (& line_buf );
1186
+ errcontext ("COPY %s, line %d: \"%s\"" ,
1187
1187
copy_relname , copy_lineno ,
1188
- MAX_COPY_DATA_DISPLAY , line_buf .data ,
1189
- (line_buf .len > MAX_COPY_DATA_DISPLAY ) ? "..." : "" );
1188
+ line_buf .data );
1190
1189
}
1191
1190
}
1192
1191
}
1193
1192
1193
+ /*
1194
+ * Make sure we don't print an unreasonable amount of COPY data in a message.
1195
+ *
1196
+ * It would seem a lot easier to just use the sprintf "precision" limit to
1197
+ * truncate the string. However, some versions of glibc have a bug/misfeature
1198
+ * that vsnprintf will always fail (return -1) if it is asked to truncate
1199
+ * a string that contains invalid byte sequences for the current encoding.
1200
+ * So, do our own truncation. We assume we can alter the StringInfo buffer
1201
+ * holding the input data.
1202
+ */
1203
+ static void
1204
+ limit_printout_length (StringInfo buf )
1205
+ {
1206
+ #define MAX_COPY_DATA_DISPLAY 100
1207
+
1208
+ int len ;
1209
+
1210
+ /* Fast path if definitely okay */
1211
+ if (buf -> len <= MAX_COPY_DATA_DISPLAY )
1212
+ return ;
1213
+
1214
+ /* Apply encoding-dependent truncation */
1215
+ len = pg_mbcliplen (buf -> data , buf -> len , MAX_COPY_DATA_DISPLAY );
1216
+ if (buf -> len <= len )
1217
+ return ; /* no need to truncate */
1218
+ buf -> len = len ;
1219
+ buf -> data [len ] = '\0' ;
1220
+
1221
+ /* Add "..." to show we truncated the input */
1222
+ appendStringInfoString (buf , "..." );
1223
+ }
1194
1224
1195
1225
/*
1196
1226
* Copy FROM file to relation.
@@ -1875,7 +1905,15 @@ CopyReadLine(void)
1875
1905
1876
1906
/*
1877
1907
* Done reading the line. Convert it to server encoding.
1908
+ *
1909
+ * Note: set line_buf_converted to true *before* attempting conversion;
1910
+ * this prevents infinite recursion during error reporting should
1911
+ * pg_client_to_server() issue an error, due to copy_in_error_callback
1912
+ * again attempting the same conversion. We'll end up issuing the message
1913
+ * without conversion, which is bad but better than nothing ...
1878
1914
*/
1915
+ line_buf_converted = true;
1916
+
1879
1917
if (change_encoding )
1880
1918
{
1881
1919
cvt = (char * ) pg_client_to_server ((unsigned char * ) line_buf .data ,
@@ -1889,8 +1927,6 @@ CopyReadLine(void)
1889
1927
}
1890
1928
}
1891
1929
1892
- line_buf_converted = true;
1893
-
1894
1930
return result ;
1895
1931
}
1896
1932
0 commit comments