@@ -7,7 +7,7 @@ use std::fmt;
7
7
use std:: io:: { self , Cursor , BufRead , Read } ;
8
8
9
9
use error:: { Error , DbError } ;
10
- use types:: { ReadWithInfo , SessionInfo , Type , ToSql , IsNull } ;
10
+ use types:: { SessionInfo , Type , ToSql , IsNull } ;
11
11
use message:: FrontendMessage :: * ;
12
12
use message:: BackendMessage :: * ;
13
13
use message:: WriteMessage ;
@@ -309,8 +309,8 @@ impl<'conn> Statement<'conn> {
309
309
try!( self . inner_execute ( "" , 0 , params) ) ;
310
310
let mut conn = self . conn . conn . borrow_mut ( ) ;
311
311
312
- match try!( conn. read_message ( ) ) {
313
- CopyInResponse { .. } => { }
312
+ let ( format , column_formats ) = match try!( conn. read_message ( ) ) {
313
+ CopyInResponse { format , column_formats } => ( format , column_formats ) ,
314
314
_ => {
315
315
loop {
316
316
match try!( conn. read_message ( ) ) {
@@ -323,53 +323,59 @@ impl<'conn> Statement<'conn> {
323
323
}
324
324
}
325
325
}
326
- }
326
+ } ;
327
+
328
+ let mut info = CopyInfo {
329
+ conn : conn,
330
+ format : Format :: from_u16 ( format as u16 ) ,
331
+ column_formats : column_formats. iter ( ) . map ( |& f| Format :: from_u16 ( f) ) . collect ( ) ,
332
+ } ;
327
333
328
334
let mut buf = [ 0 ; 16 * 1024 ] ;
329
335
loop {
330
- match fill_copy_buf ( & mut buf, r, & SessionInfo :: new ( & conn ) ) {
336
+ match fill_copy_buf ( & mut buf, r, & info ) {
331
337
Ok ( 0 ) => break ,
332
338
Ok ( len) => {
333
- try_desync ! ( conn, conn. stream. write_message(
339
+ try_desync ! ( info . conn, info . conn. stream. write_message(
334
340
& CopyData {
335
341
data: & buf[ ..len] ,
336
342
} ) ) ;
337
343
}
338
344
Err ( err) => {
339
- try!( conn. write_messages ( & [
345
+ try!( info . conn . write_messages ( & [
340
346
CopyFail {
341
347
message : "" ,
342
348
} ,
343
349
CopyDone ,
344
350
Sync ] ) ) ;
345
- match try!( conn. read_message ( ) ) {
351
+ match try!( info . conn . read_message ( ) ) {
346
352
ErrorResponse { .. } => { /* expected from the CopyFail */ }
347
353
_ => {
348
- conn. desynchronized = true ;
354
+ info . conn . desynchronized = true ;
349
355
return Err ( Error :: IoError ( bad_response ( ) ) ) ;
350
356
}
351
357
}
352
- try!( conn. wait_for_ready ( ) ) ;
358
+ try!( info . conn . wait_for_ready ( ) ) ;
353
359
return Err ( Error :: IoError ( err) ) ;
354
360
}
355
361
}
356
362
}
357
363
358
- try!( conn. write_messages ( & [ CopyDone , Sync ] ) ) ;
364
+ try!( info . conn . write_messages ( & [ CopyDone , Sync ] ) ) ;
359
365
360
- let num = match try!( conn. read_message ( ) ) {
366
+ let num = match try!( info . conn . read_message ( ) ) {
361
367
CommandComplete { tag } => util:: parse_update_count ( tag) ,
362
368
ErrorResponse { fields } => {
363
- try!( conn. wait_for_ready ( ) ) ;
369
+ try!( info . conn . wait_for_ready ( ) ) ;
364
370
return DbError :: new ( fields) ;
365
371
}
366
372
_ => {
367
- conn. desynchronized = true ;
373
+ info . conn . desynchronized = true ;
368
374
return Err ( Error :: IoError ( bad_response ( ) ) ) ;
369
375
}
370
376
} ;
371
377
372
- try!( conn. wait_for_ready ( ) ) ;
378
+ try!( info . conn . wait_for_ready ( ) ) ;
373
379
Ok ( num)
374
380
}
375
381
@@ -443,9 +449,11 @@ impl<'conn> Statement<'conn> {
443
449
} ;
444
450
445
451
Ok ( CopyOutReader {
446
- conn : conn,
447
- format : Format :: from_u16 ( format as u16 ) ,
448
- column_formats : column_formats. iter ( ) . map ( |& f| Format :: from_u16 ( f) ) . collect ( ) ,
452
+ info : CopyInfo {
453
+ conn : conn,
454
+ format : Format :: from_u16 ( format as u16 ) ,
455
+ column_formats : column_formats. iter ( ) . map ( |& f| Format :: from_u16 ( f) ) . collect ( ) ,
456
+ } ,
449
457
buf : Cursor :: new ( vec ! [ ] ) ,
450
458
finished : false ,
451
459
} )
@@ -463,7 +471,7 @@ impl<'conn> Statement<'conn> {
463
471
}
464
472
}
465
473
466
- fn fill_copy_buf < R : ReadWithInfo > ( buf : & mut [ u8 ] , r : & mut R , info : & SessionInfo )
474
+ fn fill_copy_buf < R : ReadWithInfo > ( buf : & mut [ u8 ] , r : & mut R , info : & CopyInfo )
467
475
-> io:: Result < usize > {
468
476
let mut nread = 0 ;
469
477
while nread < buf. len ( ) {
@@ -493,6 +501,44 @@ impl ColumnNew for Column {
493
501
}
494
502
}
495
503
504
+ /// A struct containing information relevant for a `COPY` operation.
505
+ pub struct CopyInfo < ' a > {
506
+ conn : RefMut < ' a , InnerConnection > ,
507
+ format : Format ,
508
+ column_formats : Vec < Format > ,
509
+ }
510
+
511
+ impl < ' a > CopyInfo < ' a > {
512
+ /// Returns the format of the overall data.
513
+ pub fn format ( & self ) -> Format {
514
+ self . format
515
+ }
516
+
517
+ /// Returns the format of the individual columns.
518
+ pub fn column_formats ( & self ) -> & [ Format ] {
519
+ & self . column_formats
520
+ }
521
+
522
+ /// Returns session info for the associated connection.
523
+ pub fn session_info < ' b > ( & ' b self ) -> SessionInfo < ' b > {
524
+ SessionInfo :: new ( & * self . conn )
525
+ }
526
+ }
527
+
528
+ /// Like `Read` except that a `CopyInfo` object is provided as well.
529
+ ///
530
+ /// All types that implement `Read` also implement this trait.
531
+ pub trait ReadWithInfo {
532
+ /// Like `Read::read`.
533
+ fn read_with_info ( & mut self , buf : & mut [ u8 ] , info : & CopyInfo ) -> io:: Result < usize > ;
534
+ }
535
+
536
+ impl < R : Read > ReadWithInfo for R {
537
+ fn read_with_info ( & mut self , buf : & mut [ u8 ] , _: & CopyInfo ) -> io:: Result < usize > {
538
+ self . read ( buf)
539
+ }
540
+ }
541
+
496
542
impl Column {
497
543
/// The name of the column.
498
544
pub fn name ( & self ) -> & str {
@@ -530,9 +576,7 @@ impl Format {
530
576
/// The underlying connection may not be used while a `CopyOutReader` exists.
531
577
/// Any attempt to do so will panic.
532
578
pub struct CopyOutReader < ' a > {
533
- conn : RefMut < ' a , InnerConnection > ,
534
- format : Format ,
535
- column_formats : Vec < Format > ,
579
+ info : CopyInfo < ' a > ,
536
580
buf : Cursor < Vec < u8 > > ,
537
581
finished : bool ,
538
582
}
@@ -544,19 +588,9 @@ impl<'a> Drop for CopyOutReader<'a> {
544
588
}
545
589
546
590
impl < ' a > CopyOutReader < ' a > {
547
- /// Returns the format of the overall data.
548
- pub fn format ( & self ) -> Format {
549
- self . format
550
- }
551
-
552
- /// Returns the format of the individual columns.
553
- pub fn column_formats ( & self ) -> & [ Format ] {
554
- & self . column_formats
555
- }
556
-
557
- /// Returns session info for the associated connection.
558
- pub fn session_info < ' b > ( & ' b self ) -> SessionInfo < ' b > {
559
- SessionInfo :: new ( & * self . conn )
591
+ /// Returns the `CopyInfo` for the current operation.
592
+ pub fn info ( & self ) -> & CopyInfo {
593
+ & self . info
560
594
}
561
595
562
596
/// Consumes the `CopyOutReader`, throwing away any unread data.
@@ -581,26 +615,26 @@ impl<'a> CopyOutReader<'a> {
581
615
return Ok ( ( ) ) ;
582
616
}
583
617
584
- match try!( self . conn . read_message ( ) ) {
618
+ match try!( self . info . conn . read_message ( ) ) {
585
619
BCopyData { data } => self . buf = Cursor :: new ( data) ,
586
620
BCopyDone => {
587
621
self . finished = true ;
588
- match try!( self . conn . read_message ( ) ) {
622
+ match try!( self . info . conn . read_message ( ) ) {
589
623
CommandComplete { .. } => { }
590
624
_ => {
591
- self . conn . desynchronized = true ;
625
+ self . info . conn . desynchronized = true ;
592
626
return Err ( Error :: IoError ( bad_response ( ) ) ) ;
593
627
}
594
628
}
595
- try!( self . conn . wait_for_ready ( ) ) ;
629
+ try!( self . info . conn . wait_for_ready ( ) ) ;
596
630
}
597
631
ErrorResponse { fields } => {
598
632
self . finished = true ;
599
- try!( self . conn . wait_for_ready ( ) ) ;
633
+ try!( self . info . conn . wait_for_ready ( ) ) ;
600
634
return DbError :: new ( fields) ;
601
635
}
602
636
_ => {
603
- self . conn . desynchronized = true ;
637
+ self . info . conn . desynchronized = true ;
604
638
return Err ( Error :: IoError ( bad_response ( ) ) ) ;
605
639
}
606
640
}
0 commit comments