1
1
use futures:: sync:: mpsc;
2
+ use postgres_protocol;
2
3
use postgres_protocol:: message:: backend:: Message ;
3
4
use postgres_protocol:: message:: frontend;
4
5
5
6
use disconnected;
6
- use error:: Error ;
7
+ use error:: { self , Error } ;
7
8
use proto:: connection:: Request ;
9
+ use proto:: execute:: ExecuteFuture ;
8
10
use proto:: prepare:: PrepareFuture ;
9
- use types:: Type ;
11
+ use proto:: statement:: Statement ;
12
+ use types:: { IsNull , ToSql , Type } ;
10
13
11
14
pub struct PendingRequest {
12
15
sender : mpsc:: UnboundedSender < Request > ,
13
- messages : Vec < u8 > ,
16
+ messages : Result < Vec < u8 > , Error > ,
14
17
}
15
18
16
19
impl PendingRequest {
17
20
pub fn send ( self ) -> Result < mpsc:: Receiver < Message > , Error > {
21
+ let messages = self . messages ?;
18
22
let ( sender, receiver) = mpsc:: channel ( 0 ) ;
19
23
self . sender
20
- . unbounded_send ( Request {
21
- messages : self . messages ,
22
- sender,
23
- } )
24
+ . unbounded_send ( Request { messages, sender } )
24
25
. map ( |_| receiver)
25
26
. map_err ( |_| disconnected ( ) )
26
27
}
@@ -36,16 +37,52 @@ impl Client {
36
37
}
37
38
38
39
pub fn prepare ( & mut self , name : String , query : & str , param_types : & [ Type ] ) -> PrepareFuture {
40
+ let pending = self . pending ( |buf| {
41
+ frontend:: parse ( & name, query, param_types. iter ( ) . map ( |t| t. oid ( ) ) , buf) ?;
42
+ frontend:: describe ( b'S' , & name, buf) ?;
43
+ frontend:: sync ( buf) ;
44
+ Ok ( ( ) )
45
+ } ) ;
46
+
47
+ PrepareFuture :: new ( pending, self . sender . clone ( ) , name)
48
+ }
49
+
50
+ pub fn execute ( & mut self , statement : & Statement , params : & [ & ToSql ] ) -> ExecuteFuture {
51
+ let pending = self . pending ( |buf| {
52
+ let r = frontend:: bind (
53
+ "" ,
54
+ statement. name ( ) ,
55
+ Some ( 1 ) ,
56
+ params. iter ( ) . zip ( statement. params ( ) ) ,
57
+ |( param, ty) , buf| match param. to_sql_checked ( ty, buf) {
58
+ Ok ( IsNull :: No ) => Ok ( postgres_protocol:: IsNull :: No ) ,
59
+ Ok ( IsNull :: Yes ) => Ok ( postgres_protocol:: IsNull :: Yes ) ,
60
+ Err ( e) => Err ( e) ,
61
+ } ,
62
+ Some ( 1 ) ,
63
+ buf,
64
+ ) ;
65
+ match r {
66
+ Ok ( ( ) ) => { }
67
+ Err ( frontend:: BindError :: Conversion ( e) ) => return Err ( error:: conversion ( e) ) ,
68
+ Err ( frontend:: BindError :: Serialization ( e) ) => return Err ( Error :: from ( e) ) ,
69
+ }
70
+ frontend:: execute ( "" , 0 , buf) ?;
71
+ frontend:: sync ( buf) ;
72
+ Ok ( ( ) )
73
+ } ) ;
74
+
75
+ ExecuteFuture :: new ( pending, statement. clone ( ) )
76
+ }
77
+
78
+ fn pending < F > ( & self , messages : F ) -> PendingRequest
79
+ where
80
+ F : FnOnce ( & mut Vec < u8 > ) -> Result < ( ) , Error > ,
81
+ {
39
82
let mut buf = vec ! [ ] ;
40
- let request = frontend:: parse ( & name, query, param_types. iter ( ) . map ( |t| t. oid ( ) ) , & mut buf)
41
- . and_then ( |( ) | frontend:: describe ( b'S' , & name, & mut buf) )
42
- . and_then ( |( ) | Ok ( frontend:: sync ( & mut buf) ) )
43
- . map ( |( ) | PendingRequest {
44
- sender : self . sender . clone ( ) ,
45
- messages : buf,
46
- } )
47
- . map_err ( Into :: into) ;
48
-
49
- PrepareFuture :: new ( request, self . sender . clone ( ) , name)
83
+ PendingRequest {
84
+ sender : self . sender . clone ( ) ,
85
+ messages : messages ( & mut buf) . map ( |( ) | buf) ,
86
+ }
50
87
}
51
88
}
0 commit comments