8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.265 2006/05/25 18:42:17 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.266 2006/05/26 22:50:02 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -95,7 +95,8 @@ typedef struct CopyStateData
95
95
/* low-level state data */
96
96
CopyDest copy_dest ; /* type of copy source/destination */
97
97
FILE * copy_file ; /* used if copy_dest == COPY_FILE */
98
- StringInfo fe_msgbuf ; /* used if copy_dest == COPY_NEW_FE */
98
+ StringInfo fe_msgbuf ; /* used for all dests during COPY TO, only
99
+ * for dest == COPY_NEW_FE in COPY FROM */
99
100
bool fe_copy ; /* true for all FE copy dests */
100
101
bool fe_eof ; /* true if detected end of copy data */
101
102
EolType eol_type ; /* EOL type of input */
@@ -287,7 +288,6 @@ SendCopyBegin(CopyState cstate)
287
288
pq_sendint (& buf , format , 2 ); /* per-column formats */
288
289
pq_endmessage (& buf );
289
290
cstate -> copy_dest = COPY_NEW_FE ;
290
- cstate -> fe_msgbuf = makeStringInfo ();
291
291
}
292
292
else if (PG_PROTOCOL_MAJOR (FrontendProtocol ) >= 2 )
293
293
{
@@ -364,23 +364,16 @@ SendCopyEnd(CopyState cstate)
364
364
{
365
365
if (cstate -> copy_dest == COPY_NEW_FE )
366
366
{
367
- if (cstate -> binary )
368
- {
369
- /* Need to flush out file trailer word */
370
- CopySendEndOfRow (cstate );
371
- }
372
- else
373
- {
374
- /* Shouldn't have any unsent data */
375
- Assert (cstate -> fe_msgbuf -> len == 0 );
376
- }
367
+ /* Shouldn't have any unsent data */
368
+ Assert (cstate -> fe_msgbuf -> len == 0 );
377
369
/* Send Copy Done message */
378
370
pq_putemptymessage ('c' );
379
371
}
380
372
else
381
373
{
382
- /* The FE/BE protocol uses \n as newline for all platforms */
383
- CopySendData (cstate , "\\.\n" , 3 );
374
+ CopySendData (cstate , "\\." , 2 );
375
+ /* Need to flush out the trailer (this also appends a newline) */
376
+ CopySendEndOfRow (cstate );
384
377
pq_endcopyout (false);
385
378
}
386
379
}
@@ -390,53 +383,34 @@ SendCopyEnd(CopyState cstate)
390
383
* CopySendString does the same for null-terminated strings
391
384
* CopySendChar does the same for single characters
392
385
* CopySendEndOfRow does the appropriate thing at end of each data row
386
+ * (data is not actually flushed except by CopySendEndOfRow)
393
387
*
394
388
* NB: no data conversion is applied by these functions
395
389
*----------
396
390
*/
397
391
static void
398
392
CopySendData (CopyState cstate , void * databuf , int datasize )
399
393
{
400
- switch (cstate -> copy_dest )
401
- {
402
- case COPY_FILE :
403
- fwrite (databuf , datasize , 1 , cstate -> copy_file );
404
- if (ferror (cstate -> copy_file ))
405
- ereport (ERROR ,
406
- (errcode_for_file_access (),
407
- errmsg ("could not write to COPY file: %m" )));
408
- break ;
409
- case COPY_OLD_FE :
410
- if (pq_putbytes ((char * ) databuf , datasize ))
411
- {
412
- /* no hope of recovering connection sync, so FATAL */
413
- ereport (FATAL ,
414
- (errcode (ERRCODE_CONNECTION_FAILURE ),
415
- errmsg ("connection lost during COPY to stdout" )));
416
- }
417
- break ;
418
- case COPY_NEW_FE :
419
- appendBinaryStringInfo (cstate -> fe_msgbuf ,
420
- (char * ) databuf , datasize );
421
- break ;
422
- }
394
+ appendBinaryStringInfo (cstate -> fe_msgbuf , (char * ) databuf , datasize );
423
395
}
424
396
425
397
static void
426
398
CopySendString (CopyState cstate , const char * str )
427
399
{
428
- CopySendData (cstate , ( void * ) str , strlen (str ));
400
+ appendBinaryStringInfo (cstate -> fe_msgbuf , str , strlen (str ));
429
401
}
430
402
431
403
static void
432
404
CopySendChar (CopyState cstate , char c )
433
405
{
434
- CopySendData (cstate , & c , 1 );
406
+ appendStringInfoCharMacro (cstate -> fe_msgbuf , c );
435
407
}
436
408
437
409
static void
438
410
CopySendEndOfRow (CopyState cstate )
439
411
{
412
+ StringInfo fe_msgbuf = cstate -> fe_msgbuf ;
413
+
440
414
switch (cstate -> copy_dest )
441
415
{
442
416
case COPY_FILE :
@@ -449,24 +423,40 @@ CopySendEndOfRow(CopyState cstate)
449
423
CopySendString (cstate , "\r\n" );
450
424
#endif
451
425
}
426
+
427
+ (void ) fwrite (fe_msgbuf -> data , fe_msgbuf -> len ,
428
+ 1 , cstate -> copy_file );
429
+ if (ferror (cstate -> copy_file ))
430
+ ereport (ERROR ,
431
+ (errcode_for_file_access (),
432
+ errmsg ("could not write to COPY file: %m" )));
452
433
break ;
453
434
case COPY_OLD_FE :
454
435
/* The FE/BE protocol uses \n as newline for all platforms */
455
436
if (!cstate -> binary )
456
437
CopySendChar (cstate , '\n' );
438
+
439
+ if (pq_putbytes (fe_msgbuf -> data , fe_msgbuf -> len ))
440
+ {
441
+ /* no hope of recovering connection sync, so FATAL */
442
+ ereport (FATAL ,
443
+ (errcode (ERRCODE_CONNECTION_FAILURE ),
444
+ errmsg ("connection lost during COPY to stdout" )));
445
+ }
457
446
break ;
458
447
case COPY_NEW_FE :
459
448
/* The FE/BE protocol uses \n as newline for all platforms */
460
449
if (!cstate -> binary )
461
450
CopySendChar (cstate , '\n' );
451
+
462
452
/* Dump the accumulated row as one CopyData message */
463
- (void ) pq_putmessage ('d' , cstate -> fe_msgbuf -> data ,
464
- cstate -> fe_msgbuf -> len );
465
- /* Reset fe_msgbuf to empty */
466
- cstate -> fe_msgbuf -> len = 0 ;
467
- cstate -> fe_msgbuf -> data [0 ] = '\0' ;
453
+ (void ) pq_putmessage ('d' , fe_msgbuf -> data , fe_msgbuf -> len );
468
454
break ;
469
455
}
456
+
457
+ /* Reset fe_msgbuf to empty */
458
+ fe_msgbuf -> len = 0 ;
459
+ fe_msgbuf -> data [0 ] = '\0' ;
470
460
}
471
461
472
462
/*
@@ -1237,6 +1227,9 @@ CopyTo(CopyState cstate)
1237
1227
attr_count = list_length (cstate -> attnumlist );
1238
1228
null_print_client = cstate -> null_print ; /* default */
1239
1229
1230
+ /* We use fe_msgbuf as a per-row buffer regardless of copy_dest */
1231
+ cstate -> fe_msgbuf = makeStringInfo ();
1232
+
1240
1233
/* Get info about the columns we need to process. */
1241
1234
out_functions = (FmgrInfo * ) palloc (num_phys_attrs * sizeof (FmgrInfo ));
1242
1235
force_quote = (bool * ) palloc (num_phys_attrs * sizeof (bool ));
@@ -1423,6 +1416,8 @@ CopyTo(CopyState cstate)
1423
1416
{
1424
1417
/* Generate trailer for a binary copy */
1425
1418
CopySendInt16 (cstate , -1 );
1419
+ /* Need to flush out the trailer */
1420
+ CopySendEndOfRow (cstate );
1426
1421
}
1427
1422
1428
1423
MemoryContextDelete (mycontext );
0 commit comments