1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Fix spurious errors in COPY FROM (FORMAT {text,csv}).

The SIMD path for these commands reads ahead into the input buffer
via CopyLoadInputBuf(), which reports encoding and conversion
errors.  The problem is that the errant data might lie beyond the
end-of-copy marker, which we aren't copying and thus needn't error
for.  To fix, add a "speculative" parameter to CopyLoadInputBuf()
that defers these errors, and use it in the SIMD path.  The errors
are instead reported only if we actually reach the errant data.
Testing indicates this does not meaningfully impact performance.

Oversight in commit e0a3a3fd53.

Reviewed-by: Greg Burd <greg@burd.me>
Reviewed-by: Nazir Bilal Yavuz <byavuz81@gmail.com>
Discussion: https://postgr.es/m/apWOr1kgVSqweBnU%40nathan
Backpatch-through: 19
This commit is contained in:
Nathan Bossart
2026-09-01 14:20:16 -05:00
parent 938f4f8f34
commit f26ab219e2

View File

@@ -167,7 +167,7 @@ static int CopyGetData(CopyFromState cstate, void *databuf,
int minread, int maxread);
static inline bool CopyGetInt32(CopyFromState cstate, int32 *val);
static inline bool CopyGetInt16(CopyFromState cstate, int16 *val);
static void CopyLoadInputBuf(CopyFromState cstate);
static void CopyLoadInputBuf(CopyFromState cstate, bool speculative);
static int CopyReadBinaryData(CopyFromState cstate, char *dest, int nbytes);
void
@@ -651,9 +651,14 @@ CopyLoadRawBuf(CopyFromState cstate)
*
* If INPUT_BUF_BYTES(cstate) > 0, the unprocessed bytes are moved to the start
* of the buffer and then we load more data after that.
*
* If "speculative" is true, this function skips reporting any encoding or
* conversion errors, provided there are still data for the caller to process.
* Such callers must be prepared for this function to return without loading
* anything.
*/
static void
CopyLoadInputBuf(CopyFromState cstate)
CopyLoadInputBuf(CopyFromState cstate, bool speculative)
{
int nbytes = INPUT_BUF_BYTES(cstate);
@@ -681,10 +686,16 @@ CopyLoadInputBuf(CopyFromState cstate)
/*
* If we reached an invalid byte sequence, or we're at an incomplete
* multi-byte character but there is no more raw input data, report
* conversion error.
* conversion error. As an exception, if "speculative" is true and
* there are still data for the caller to process, just return
* instead.
*/
if (cstate->input_reached_error)
{
if (speculative && INPUT_BUF_BYTES(cstate) > 0)
return;
CopyConversionError(cstate);
}
/* no more input, and everything has been converted */
if (cstate->input_reached_eof)
@@ -1381,7 +1392,7 @@ CopyReadLineTextSIMDHelper(CopyFromState cstate, bool is_csv,
{
REFILL_LINEBUF;
CopyLoadInputBuf(cstate);
CopyLoadInputBuf(cstate, true);
/* update our local variables */
*hit_eof_p = cstate->input_reached_eof;
input_buf_ptr = cstate->input_buf_index;
@@ -1566,7 +1577,7 @@ CopyReadLineText(CopyFromState cstate, bool is_csv)
{
REFILL_LINEBUF;
CopyLoadInputBuf(cstate);
CopyLoadInputBuf(cstate, false);
/* update our local variables */
hit_eof = cstate->input_reached_eof;
input_buf_ptr = cstate->input_buf_index;