88 *
99 *
1010 * 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 $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -139,6 +139,7 @@ static Datum CopyReadBinaryAttribute(int column_no, FmgrInfo *flinfo,
139139Oid typelem ,bool * isnull );
140140static void CopyAttributeOut (char * string ,char * delim );
141141static List * CopyGetAttnums (Relation rel ,List * attnamelist );
142+ static void limit_printout_length (StringInfo buf );
142143
143144/* Internal communications functions */
144145static void SendCopyBegin (bool binary ,int natts );
@@ -1140,8 +1141,6 @@ CopyTo(Relation rel, List *attnumlist, bool binary, bool oids,
11401141static void
11411142copy_in_error_callback (void * arg )
11421143{
1143- #define MAX_COPY_DATA_DISPLAY 100
1144-
11451144if (copy_binary )
11461145{
11471146/* can't usefully display the data */
@@ -1156,17 +1155,18 @@ copy_in_error_callback(void *arg)
11561155if (copy_attname )
11571156{
11581157/* 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\"" ,
11601160copy_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 );
11631162}
11641163else
11651164{
11661165/* error is relevant to a particular line */
11671166if (!line_buf_converted )
11681167{
11691168/* didn't convert the encoding yet... */
1169+ line_buf_converted = true;
11701170if (client_encoding != server_encoding )
11711171{
11721172char * cvt ;
@@ -1181,16 +1181,46 @@ copy_in_error_callback(void *arg)
11811181appendBinaryStringInfo (& line_buf ,cvt ,strlen (cvt ));
11821182}
11831183}
1184- line_buf_converted = true;
11851184}
1186- errcontext ("COPY %s, line %d: \"%.*s%s\"" ,
1185+ limit_printout_length (& line_buf );
1186+ errcontext ("COPY %s, line %d: \"%s\"" ,
11871187copy_relname ,copy_lineno ,
1188- MAX_COPY_DATA_DISPLAY ,line_buf .data ,
1189- (line_buf .len > MAX_COPY_DATA_DISPLAY ) ?"..." :"" );
1188+ line_buf .data );
11901189}
11911190}
11921191}
11931192
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+ }
11941224
11951225/*
11961226 * Copy FROM file to relation.
@@ -1875,7 +1905,15 @@ CopyReadLine(void)
18751905
18761906/*
18771907 * 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 ...
18781914 */
1915+ line_buf_converted = true;
1916+
18791917if (change_encoding )
18801918{
18811919cvt = (char * )pg_client_to_server ((unsignedchar * )line_buf .data ,
@@ -1889,8 +1927,6 @@ CopyReadLine(void)
18891927}
18901928}
18911929
1892- line_buf_converted = true;
1893-
18941930return result ;
18951931}
18961932