1
1
use antidote:: Mutex ;
2
2
use futures:: sync:: mpsc;
3
+ use futures:: { AsyncSink , Sink , Stream } ;
3
4
use postgres_protocol;
4
5
use postgres_protocol:: message:: backend:: Message ;
5
6
use postgres_protocol:: message:: frontend;
6
7
use std:: collections:: HashMap ;
8
+ use std:: error:: Error as StdError ;
7
9
use std:: sync:: { Arc , Weak } ;
8
10
9
11
use disconnected;
10
12
use error:: { self , Error } ;
11
- use proto:: connection:: Request ;
13
+ use proto:: connection:: { Request , RequestMessages } ;
14
+ use proto:: copy_in:: { CopyInFuture , CopyInReceiver , CopyMessage } ;
12
15
use proto:: copy_out:: CopyOutStream ;
13
16
use proto:: execute:: ExecuteFuture ;
14
17
use proto:: prepare:: PrepareFuture ;
@@ -17,7 +20,7 @@ use proto::simple_query::SimpleQueryFuture;
17
20
use proto:: statement:: Statement ;
18
21
use types:: { IsNull , Oid , ToSql , Type } ;
19
22
20
- pub struct PendingRequest ( Result < Vec < u8 > , Error > ) ;
23
+ pub struct PendingRequest ( Result < RequestMessages , Error > ) ;
21
24
22
25
pub struct WeakClient ( Weak < Inner > ) ;
23
26
@@ -122,17 +125,45 @@ impl Client {
122
125
}
123
126
124
127
pub fn execute ( & self , statement : & Statement , params : & [ & ToSql ] ) -> ExecuteFuture {
125
- let pending = self . pending_execute ( statement, params) ;
128
+ let pending = PendingRequest (
129
+ self . excecute_message ( statement, params)
130
+ . map ( RequestMessages :: Single ) ,
131
+ ) ;
126
132
ExecuteFuture :: new ( self . clone ( ) , pending, statement. clone ( ) )
127
133
}
128
134
129
135
pub fn query ( & self , statement : & Statement , params : & [ & ToSql ] ) -> QueryStream {
130
- let pending = self . pending_execute ( statement, params) ;
136
+ let pending = PendingRequest (
137
+ self . excecute_message ( statement, params)
138
+ . map ( RequestMessages :: Single ) ,
139
+ ) ;
131
140
QueryStream :: new ( self . clone ( ) , pending, statement. clone ( ) )
132
141
}
133
142
143
+ pub fn copy_in < S > ( & self , statement : & Statement , params : & [ & ToSql ] , stream : S ) -> CopyInFuture < S >
144
+ where
145
+ S : Stream < Item = Vec < u8 > > ,
146
+ S :: Error : Into < Box < StdError + Sync + Send > > ,
147
+ {
148
+ let ( mut sender, receiver) = mpsc:: channel ( 0 ) ;
149
+ let pending = PendingRequest ( self . excecute_message ( statement, params) . map ( |buf| {
150
+ match sender. start_send ( CopyMessage :: Data ( buf) ) {
151
+ Ok ( AsyncSink :: Ready ) => { }
152
+ _ => unreachable ! ( "channel should have capacity" ) ,
153
+ }
154
+ RequestMessages :: CopyIn {
155
+ receiver : CopyInReceiver :: new ( receiver) ,
156
+ pending_message : None ,
157
+ }
158
+ } ) ) ;
159
+ CopyInFuture :: new ( self . clone ( ) , pending, statement. clone ( ) , stream, sender)
160
+ }
161
+
134
162
pub fn copy_out ( & self , statement : & Statement , params : & [ & ToSql ] ) -> CopyOutStream {
135
- let pending = self . pending_execute ( statement, params) ;
163
+ let pending = PendingRequest (
164
+ self . excecute_message ( statement, params)
165
+ . map ( RequestMessages :: Single ) ,
166
+ ) ;
136
167
CopyOutStream :: new ( self . clone ( ) , pending, statement. clone ( ) )
137
168
}
138
169
@@ -142,42 +173,41 @@ impl Client {
142
173
frontend:: sync ( & mut buf) ;
143
174
let ( sender, _) = mpsc:: channel ( 0 ) ;
144
175
let _ = self . 0 . sender . unbounded_send ( Request {
145
- messages : buf,
176
+ messages : RequestMessages :: Single ( buf) ,
146
177
sender,
147
178
} ) ;
148
179
}
149
180
150
- fn pending_execute ( & self , statement : & Statement , params : & [ & ToSql ] ) -> PendingRequest {
151
- self . pending ( |buf| {
152
- let r = frontend:: bind (
153
- "" ,
154
- statement. name ( ) ,
155
- Some ( 1 ) ,
156
- params. iter ( ) . zip ( statement. params ( ) ) ,
157
- |( param, ty) , buf| match param. to_sql_checked ( ty, buf) {
158
- Ok ( IsNull :: No ) => Ok ( postgres_protocol:: IsNull :: No ) ,
159
- Ok ( IsNull :: Yes ) => Ok ( postgres_protocol:: IsNull :: Yes ) ,
160
- Err ( e) => Err ( e) ,
161
- } ,
162
- Some ( 1 ) ,
163
- buf,
164
- ) ;
165
- match r {
166
- Ok ( ( ) ) => { }
167
- Err ( frontend:: BindError :: Conversion ( e) ) => return Err ( error:: conversion ( e) ) ,
168
- Err ( frontend:: BindError :: Serialization ( e) ) => return Err ( Error :: from ( e) ) ,
169
- }
170
- frontend:: execute ( "" , 0 , buf) ?;
171
- frontend:: sync ( buf) ;
172
- Ok ( ( ) )
173
- } )
181
+ fn excecute_message ( & self , statement : & Statement , params : & [ & ToSql ] ) -> Result < Vec < u8 > , Error > {
182
+ let mut buf = vec ! [ ] ;
183
+ let r = frontend:: bind (
184
+ "" ,
185
+ statement. name ( ) ,
186
+ Some ( 1 ) ,
187
+ params. iter ( ) . zip ( statement. params ( ) ) ,
188
+ |( param, ty) , buf| match param. to_sql_checked ( ty, buf) {
189
+ Ok ( IsNull :: No ) => Ok ( postgres_protocol:: IsNull :: No ) ,
190
+ Ok ( IsNull :: Yes ) => Ok ( postgres_protocol:: IsNull :: Yes ) ,
191
+ Err ( e) => Err ( e) ,
192
+ } ,
193
+ Some ( 1 ) ,
194
+ & mut buf,
195
+ ) ;
196
+ match r {
197
+ Ok ( ( ) ) => { }
198
+ Err ( frontend:: BindError :: Conversion ( e) ) => return Err ( error:: conversion ( e) ) ,
199
+ Err ( frontend:: BindError :: Serialization ( e) ) => return Err ( Error :: from ( e) ) ,
200
+ }
201
+ frontend:: execute ( "" , 0 , & mut buf) ?;
202
+ frontend:: sync ( & mut buf) ;
203
+ Ok ( buf)
174
204
}
175
205
176
206
fn pending < F > ( & self , messages : F ) -> PendingRequest
177
207
where
178
208
F : FnOnce ( & mut Vec < u8 > ) -> Result < ( ) , Error > ,
179
209
{
180
210
let mut buf = vec ! [ ] ;
181
- PendingRequest ( messages ( & mut buf) . map ( |( ) | buf) )
211
+ PendingRequest ( messages ( & mut buf) . map ( |( ) | RequestMessages :: Single ( buf) ) )
182
212
}
183
213
}
0 commit comments