Commit f05cfd2c authored by Tom Lane's avatar Tom Lane

Fix failure to think clearly about encoding conversion errors in COPY.

We can't regurgitate the unconverted string as I first thought, because
the elog.c mechanisms will assume the error message data is in the server
encoding and attempt a reverse conversion.  Eventually it might be worth
providing a short-circuit path to support this, but for now the simplest
solution is to abandon trying to report back the line contents after a
conversion failure.  Per bug report from Sil Lee, 27-Oct-2004.
parent 08510856
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.232 2004/09/13 20:06:27 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.233 2004/10/29 19:18:22 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1401,29 +1401,26 @@ copy_in_error_callback(void *arg) ...@@ -1401,29 +1401,26 @@ copy_in_error_callback(void *arg)
else else
{ {
/* error is relevant to a particular line */ /* error is relevant to a particular line */
if (!line_buf_converted) if (line_buf_converted ||
client_encoding == server_encoding)
{ {
/* didn't convert the encoding yet... */ limit_printout_length(&line_buf);
line_buf_converted = true; errcontext("COPY %s, line %d: \"%s\"",
if (client_encoding != server_encoding) copy_relname, copy_lineno,
{ line_buf.data);
char *cvt; }
else
cvt = (char *) pg_client_to_server((unsigned char *) line_buf.data, {
line_buf.len); /*
if (cvt != line_buf.data) * Here, the line buffer is still in a foreign encoding,
{ * and indeed it's quite likely that the error is precisely
/* transfer converted data back to line_buf */ * a failure to do encoding conversion (ie, bad data). We
line_buf.len = 0; * dare not try to convert it, and at present there's no way
line_buf.data[0] = '\0'; * to regurgitate it without conversion. So we have to punt
appendBinaryStringInfo(&line_buf, cvt, strlen(cvt)); * and just report the line number.
} */
} errcontext("COPY %s, line %d", copy_relname, copy_lineno);
} }
limit_printout_length(&line_buf);
errcontext("COPY %s, line %d: \"%s\"",
copy_relname, copy_lineno,
line_buf.data);
} }
} }
} }
...@@ -2175,16 +2172,7 @@ CopyReadLine(void) ...@@ -2175,16 +2172,7 @@ CopyReadLine(void)
/* /*
* Done reading the line. Convert it to server encoding. * Done reading the line. Convert it to server encoding.
*
* Note: set line_buf_converted to true *before* attempting conversion;
* this prevents infinite recursion during error reporting should
* pg_client_to_server() issue an error, due to copy_in_error_callback
* again attempting the same conversion. We'll end up issuing the
* message without conversion, which is bad but better than nothing
* ...
*/ */
line_buf_converted = true;
if (change_encoding) if (change_encoding)
{ {
cvt = (char *) pg_client_to_server((unsigned char *) line_buf.data, cvt = (char *) pg_client_to_server((unsigned char *) line_buf.data,
...@@ -2198,6 +2186,9 @@ CopyReadLine(void) ...@@ -2198,6 +2186,9 @@ CopyReadLine(void)
} }
} }
/* Now it's safe to use the buffer in error messages */
line_buf_converted = true;
return result; return result;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment