@@ -183,6 +183,7 @@ typedef struct CopyStateData
183183 */
184184StringInfoData line_buf ;
185185bool 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,
292293CommandId mycid ,int hi_options ,
293294ResultRelInfo * resultRelInfo ,TupleTableSlot * myslot ,
294295BulkInsertState 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}
19241926else
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{
19291941char * lineval ;
19301942
@@ -1935,14 +1947,6 @@ CopyFromErrorCallback(void *arg)
19351947}
19361948else
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- */
19461950errcontext ("COPY %s, line %d" ,
19471951cstate -> cur_relname ,cstate -> cur_lineno );
19481952}
@@ -2012,6 +2016,7 @@ CopyFrom(CopyState cstate)
20122016#define MAX_BUFFERED_TUPLES 1000
20132017HeapTuple * bufferedTuples = NULL ;/* initialize to silence warning */
20142018Size bufferedTuplesSize = 0 ;
2019+ int firstBufferedLineNo = 0 ;
20152020
20162021Assert (cstate -> rel );
20172022
@@ -2243,6 +2248,8 @@ CopyFrom(CopyState cstate)
22432248if (useHeapMultiInsert )
22442249{
22452250/* Add this tuple to the tuple buffer */
2251+ if (nBufferedTuples == 0 )
2252+ firstBufferedLineNo = cstate -> cur_lineno ;
22462253bufferedTuples [nBufferedTuples ++ ]= tuple ;
22472254bufferedTuplesSize += tuple -> t_len ;
22482255
@@ -2257,7 +2264,8 @@ CopyFrom(CopyState cstate)
22572264{
22582265CopyFromInsertBatch (cstate ,estate ,mycid ,hi_options ,
22592266resultRelInfo ,myslot ,bistate ,
2260- nBufferedTuples ,bufferedTuples );
2267+ nBufferedTuples ,bufferedTuples ,
2268+ firstBufferedLineNo );
22612269nBufferedTuples = 0 ;
22622270bufferedTuplesSize = 0 ;
22632271}
@@ -2293,7 +2301,8 @@ CopyFrom(CopyState cstate)
22932301if (nBufferedTuples > 0 )
22942302CopyFromInsertBatch (cstate ,estate ,mycid ,hi_options ,
22952303resultRelInfo ,myslot ,bistate ,
2296- nBufferedTuples ,bufferedTuples );
2304+ nBufferedTuples ,bufferedTuples ,
2305+ firstBufferedLineNo );
22972306
22982307/* Done, clean up */
22992308error_context_stack = errcallback .previous ;
@@ -2336,10 +2345,19 @@ static void
23362345CopyFromInsertBatch (CopyState cstate ,EState * estate ,CommandId mycid ,
23372346int hi_options ,ResultRelInfo * resultRelInfo ,
23382347TupleTableSlot * myslot ,BulkInsertState bistate ,
2339- int nBufferedTuples ,HeapTuple * bufferedTuples )
2348+ int nBufferedTuples ,HeapTuple * bufferedTuples ,
2349+ int firstBufferedLineNo )
23402350{
23412351MemoryContext oldcontext ;
23422352int 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{
23652383List * recheckIndexes ;
23662384
2385+ cstate -> cur_lineno = firstBufferedLineNo + i ;
23672386ExecStoreTuple (bufferedTuples [i ],myslot ,InvalidBuffer , false);
23682387recheckIndexes =
23692388ExecInsertIndexTuples (myslot ,& (bufferedTuples [i ]-> t_self ),
@@ -2383,10 +2402,16 @@ CopyFromInsertBatch(CopyState cstate, EState *estate, CommandId mycid,
23832402resultRelInfo -> ri_TrigDesc -> trig_insert_after_row )
23842403{
23852404for (i = 0 ;i < nBufferedTuples ;i ++ )
2405+ {
2406+ cstate -> cur_lineno = firstBufferedLineNo + i ;
23862407ExecARInsertTriggers (estate ,resultRelInfo ,
23872408bufferedTuples [i ],
23882409NIL );
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)
29152940bool result ;
29162941
29172942resetStringInfo (& cstate -> line_buf );
2943+ cstate -> line_buf_valid = true;
29182944
29192945/* Mark that encoding conversion hasn't occurred yet */
29202946cstate -> line_buf_converted = false;