@@ -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 );
296298static bool CopyReadLine (CopyState cstate );
297299static bool CopyReadLineText (CopyState cstate );
298300static 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
23362345CopyFromInsertBatch (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