Skip to content

Commit fcf91c0

Browse files
committed
Print line number correctly in COPY.
When COPY uses the multi-insert method to insert a batch of tuples into the heap at a time, incorrect line number was printed if something went wrong in inserting the index tuples (primary key failure, for exampl), or processing after row triggers. Fixes bug #8173 reported by Lloyd Albin. Backpatch to 9.2, where the multi- insert code was added.
1 parent e7e005e commit fcf91c0

File tree

1 file changed

+40
-14
lines changed

1 file changed

+40
-14
lines changed

src/backend/commands/copy.c

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,7 @@ typedef struct CopyStateData
176176
*/
177177
StringInfoData line_buf;
178178
bool line_buf_converted; /* converted to server encoding? */
179+
bool line_buf_valid; /* contains the row being processed? */
179180

180181
/*
181182
* Finally, raw_buf holds raw data read from the data source (file or
@@ -283,7 +284,8 @@ static void CopyFromInsertBatch(CopyState cstate, EState *estate,
283284
CommandId mycid, int hi_options,
284285
ResultRelInfo *resultRelInfo, TupleTableSlot *myslot,
285286
BulkInsertState bistate,
286-
int nBufferedTuples, HeapTuple *bufferedTuples);
287+
int nBufferedTuples, HeapTuple *bufferedTuples,
288+
int firstBufferedLineNo);
287289
static bool CopyReadLine(CopyState cstate);
288290
static bool CopyReadLineText(CopyState cstate);
289291
static int CopyReadAttributesText(CopyState cstate);
@@ -1776,8 +1778,18 @@ CopyFromErrorCallback(void *arg)
17761778
}
17771779
else
17781780
{
1779-
/* error is relevant to a particular line */
1780-
if (cstate->line_buf_converted || !cstate->need_transcoding)
1781+
/*
1782+
* Error is relevant to a particular line.
1783+
*
1784+
* If line_buf still contains the correct line, and it's already
1785+
* transcoded, print it. If it's still in a foreign encoding,
1786+
* it's quite likely that the error is precisely a failure to do
1787+
* encoding conversion (ie, bad data). We dare not try to convert
1788+
* it, and at present there's no way to regurgitate it without
1789+
* conversion. So we have to punt and just report the line number.
1790+
*/
1791+
if (cstate->line_buf_valid &&
1792+
(cstate->line_buf_converted || !cstate->need_transcoding))
17811793
{
17821794
char *lineval;
17831795

@@ -1788,14 +1800,6 @@ CopyFromErrorCallback(void *arg)
17881800
}
17891801
else
17901802
{
1791-
/*
1792-
* Here, the line buffer is still in a foreign encoding, and
1793-
* indeed it's quite likely that the error is precisely a
1794-
* failure to do encoding conversion (ie, bad data). We dare
1795-
* not try to convert it, and at present there's no way to
1796-
* regurgitate it without conversion. So we have to punt and
1797-
* just report the line number.
1798-
*/
17991803
errcontext("COPY %s, line %d",
18001804
cstate->cur_relname, cstate->cur_lineno);
18011805
}
@@ -1865,6 +1869,7 @@ CopyFrom(CopyState cstate)
18651869
#define MAX_BUFFERED_TUPLES 1000
18661870
HeapTuple *bufferedTuples = NULL; /* initialize to silence warning */
18671871
Size bufferedTuplesSize = 0;
1872+
int firstBufferedLineNo = 0;
18681873

18691874
Assert(cstate->rel);
18701875

@@ -2064,6 +2069,8 @@ CopyFrom(CopyState cstate)
20642069
if (useHeapMultiInsert)
20652070
{
20662071
/* Add this tuple to the tuple buffer */
2072+
if (nBufferedTuples == 0)
2073+
firstBufferedLineNo = cstate->cur_lineno;
20672074
bufferedTuples[nBufferedTuples++] = tuple;
20682075
bufferedTuplesSize += tuple->t_len;
20692076

@@ -2078,7 +2085,8 @@ CopyFrom(CopyState cstate)
20782085
{
20792086
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
20802087
resultRelInfo, myslot, bistate,
2081-
nBufferedTuples, bufferedTuples);
2088+
nBufferedTuples, bufferedTuples,
2089+
firstBufferedLineNo);
20822090
nBufferedTuples = 0;
20832091
bufferedTuplesSize = 0;
20842092
}
@@ -2114,7 +2122,8 @@ CopyFrom(CopyState cstate)
21142122
if (nBufferedTuples > 0)
21152123
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
21162124
resultRelInfo, myslot, bistate,
2117-
nBufferedTuples, bufferedTuples);
2125+
nBufferedTuples, bufferedTuples,
2126+
firstBufferedLineNo);
21182127

21192128
/* Done, clean up */
21202129
error_context_stack = errcontext.previous;
@@ -2157,10 +2166,19 @@ static void
21572166
CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
21582167
int hi_options, ResultRelInfo *resultRelInfo,
21592168
TupleTableSlot *myslot, BulkInsertState bistate,
2160-
int nBufferedTuples, HeapTuple *bufferedTuples)
2169+
int nBufferedTuples, HeapTuple *bufferedTuples,
2170+
int firstBufferedLineNo)
21612171
{
21622172
MemoryContext oldcontext;
21632173
int i;
2174+
int save_cur_lineno;
2175+
2176+
/*
2177+
* Print error context information correctly, if one of the operations
2178+
* below fail.
2179+
*/
2180+
cstate->line_buf_valid = false;
2181+
save_cur_lineno = cstate->cur_lineno;
21642182

21652183
/*
21662184
* heap_multi_insert leaks memory, so switch to short-lived memory context
@@ -2185,6 +2203,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
21852203
{
21862204
List *recheckIndexes;
21872205

2206+
cstate->cur_lineno = firstBufferedLineNo + i;
21882207
ExecStoreTuple(bufferedTuples[i], myslot, InvalidBuffer, false);
21892208
recheckIndexes =
21902209
ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self),
@@ -2204,10 +2223,16 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
22042223
resultRelInfo->ri_TrigDesc->trig_insert_after_row)
22052224
{
22062225
for (i = 0; i < nBufferedTuples; i++)
2226+
{
2227+
cstate->cur_lineno = firstBufferedLineNo + i;
22072228
ExecARInsertTriggers(estate, resultRelInfo,
22082229
bufferedTuples[i],
22092230
NIL);
2231+
}
22102232
}
2233+
2234+
/* reset cur_lineno to where we were */
2235+
cstate->cur_lineno = save_cur_lineno;
22112236
}
22122237

22132238
/*
@@ -2715,6 +2740,7 @@ CopyReadLine(CopyState cstate)
27152740
bool result;
27162741

27172742
resetStringInfo(&cstate->line_buf);
2743+
cstate->line_buf_valid = true;
27182744

27192745
/* Mark that encoding conversion hasn't occurred yet */
27202746
cstate->line_buf_converted = false;

0 commit comments

Comments
 (0)