Skip to content

Commit e2ef289

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 bc41ef4 commit e2ef289

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
@@ -183,6 +183,7 @@ typedef struct CopyStateData
183183
*/
184184
StringInfoData line_buf;
185185
bool line_buf_converted; /* converted to server encoding? */
186+
bool line_buf_valid; /* contains the row being processed? */
186187

187188
/*
188189
* Finally, raw_buf holds raw data read from the data source (file or
@@ -292,7 +293,8 @@ static void CopyFromInsertBatch(CopyState cstate, EState *estate,
292293
CommandId mycid, int hi_options,
293294
ResultRelInfo *resultRelInfo, TupleTableSlot *myslot,
294295
BulkInsertState bistate,
295-
int nBufferedTuples, HeapTuple *bufferedTuples);
296+
int nBufferedTuples, HeapTuple *bufferedTuples,
297+
int firstBufferedLineNo);
296298
static bool CopyReadLine(CopyState cstate);
297299
static bool CopyReadLineText(CopyState cstate);
298300
static int CopyReadAttributesText(CopyState cstate);
@@ -1923,8 +1925,18 @@ CopyFromErrorCallback(void *arg)
19231925
}
19241926
else
19251927
{
1926-
/* error is relevant to a particular line */
1927-
if (cstate->line_buf_converted || !cstate->need_transcoding)
1928+
/*
1929+
* Error is relevant to a particular line.
1930+
*
1931+
* If line_buf still contains the correct line, and it's already
1932+
* transcoded, print it. If it's still in a foreign encoding,
1933+
* it's quite likely that the error is precisely a failure to do
1934+
* encoding conversion (ie, bad data). We dare not try to convert
1935+
* it, and at present there's no way to regurgitate it without
1936+
* conversion. So we have to punt and just report the line number.
1937+
*/
1938+
if (cstate->line_buf_valid &&
1939+
(cstate->line_buf_converted || !cstate->need_transcoding))
19281940
{
19291941
char *lineval;
19301942

@@ -1935,14 +1947,6 @@ CopyFromErrorCallback(void *arg)
19351947
}
19361948
else
19371949
{
1938-
/*
1939-
* Here, the line buffer is still in a foreign encoding, and
1940-
* indeed it's quite likely that the error is precisely a
1941-
* failure to do encoding conversion (ie, bad data). We dare
1942-
* not try to convert it, and at present there's no way to
1943-
* regurgitate it without conversion. So we have to punt and
1944-
* just report the line number.
1945-
*/
19461950
errcontext("COPY %s, line %d",
19471951
cstate->cur_relname, cstate->cur_lineno);
19481952
}
@@ -2012,6 +2016,7 @@ CopyFrom(CopyState cstate)
20122016
#define MAX_BUFFERED_TUPLES 1000
20132017
HeapTuple *bufferedTuples = NULL; /* initialize to silence warning */
20142018
Size bufferedTuplesSize = 0;
2019+
int firstBufferedLineNo = 0;
20152020

20162021
Assert(cstate->rel);
20172022

@@ -2243,6 +2248,8 @@ CopyFrom(CopyState cstate)
22432248
if (useHeapMultiInsert)
22442249
{
22452250
/* Add this tuple to the tuple buffer */
2251+
if (nBufferedTuples == 0)
2252+
firstBufferedLineNo = cstate->cur_lineno;
22462253
bufferedTuples[nBufferedTuples++] = tuple;
22472254
bufferedTuplesSize += tuple->t_len;
22482255

@@ -2257,7 +2264,8 @@ CopyFrom(CopyState cstate)
22572264
{
22582265
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
22592266
resultRelInfo, myslot, bistate,
2260-
nBufferedTuples, bufferedTuples);
2267+
nBufferedTuples, bufferedTuples,
2268+
firstBufferedLineNo);
22612269
nBufferedTuples = 0;
22622270
bufferedTuplesSize = 0;
22632271
}
@@ -2293,7 +2301,8 @@ CopyFrom(CopyState cstate)
22932301
if (nBufferedTuples > 0)
22942302
CopyFromInsertBatch(cstate, estate, mycid, hi_options,
22952303
resultRelInfo, myslot, bistate,
2296-
nBufferedTuples, bufferedTuples);
2304+
nBufferedTuples, bufferedTuples,
2305+
firstBufferedLineNo);
22972306

22982307
/* Done, clean up */
22992308
error_context_stack = errcallback.previous;
@@ -2336,10 +2345,19 @@ static void
23362345
CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
23372346
int hi_options, ResultRelInfo *resultRelInfo,
23382347
TupleTableSlot *myslot, BulkInsertState bistate,
2339-
int nBufferedTuples, HeapTuple *bufferedTuples)
2348+
int nBufferedTuples, HeapTuple *bufferedTuples,
2349+
int firstBufferedLineNo)
23402350
{
23412351
MemoryContext oldcontext;
23422352
int i;
2353+
int save_cur_lineno;
2354+
2355+
/*
2356+
* Print error context information correctly, if one of the operations
2357+
* below fail.
2358+
*/
2359+
cstate->line_buf_valid = false;
2360+
save_cur_lineno = cstate->cur_lineno;
23432361

23442362
/*
23452363
* heap_multi_insert leaks memory, so switch to short-lived memory context
@@ -2364,6 +2382,7 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
23642382
{
23652383
List *recheckIndexes;
23662384

2385+
cstate->cur_lineno = firstBufferedLineNo + i;
23672386
ExecStoreTuple(bufferedTuples[i], myslot, InvalidBuffer, false);
23682387
recheckIndexes =
23692388
ExecInsertIndexTuples(myslot, &(bufferedTuples[i]->t_self),
@@ -2383,10 +2402,16 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
23832402
resultRelInfo->ri_TrigDesc->trig_insert_after_row)
23842403
{
23852404
for (i = 0; i < nBufferedTuples; i++)
2405+
{
2406+
cstate->cur_lineno = firstBufferedLineNo + i;
23862407
ExecARInsertTriggers(estate, resultRelInfo,
23872408
bufferedTuples[i],
23882409
NIL);
2410+
}
23892411
}
2412+
2413+
/* reset cur_lineno to where we were */
2414+
cstate->cur_lineno = save_cur_lineno;
23902415
}
23912416

23922417
/*
@@ -2915,6 +2940,7 @@ CopyReadLine(CopyState cstate)
29152940
bool result;
29162941

29172942
resetStringInfo(&cstate->line_buf);
2943+
cstate->line_buf_valid = true;
29182944

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

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy