1
1
use fallible_iterator:: FallibleIterator ;
2
2
use futures:: sync:: mpsc;
3
- use futures:: { Poll , Stream } ;
4
- use postgres_protocol:: message:: backend:: { Message , ParameterDescriptionBody , RowDescriptionBody } ;
3
+ use futures:: { Future , Poll , Stream } ;
4
+ use postgres_protocol:: message:: backend:: Message ;
5
5
use state_machine_future:: RentToOwn ;
6
+ use std:: mem;
7
+ use std:: vec;
6
8
7
9
use error:: { self , Error } ;
8
- use proto:: client:: PendingRequest ;
10
+ use proto:: client:: { Client , PendingRequest } ;
9
11
use proto:: connection:: Request ;
10
12
use proto:: statement:: Statement ;
11
- use types:: Type ;
13
+ use proto:: typeinfo:: TypeinfoFuture ;
14
+ use types:: { Oid , Type } ;
12
15
use Column ;
13
16
use { bad_response, disconnected} ;
14
17
@@ -19,33 +22,57 @@ pub enum Prepare {
19
22
request : PendingRequest ,
20
23
sender : mpsc:: UnboundedSender < Request > ,
21
24
name : String ,
25
+ client : Client ,
22
26
} ,
23
27
#[ state_machine_future( transitions( ReadParameterDescription ) ) ]
24
28
ReadParseComplete {
25
29
sender : mpsc:: UnboundedSender < Request > ,
26
30
receiver : mpsc:: Receiver < Message > ,
27
31
name : String ,
32
+ client : Client ,
28
33
} ,
29
34
#[ state_machine_future( transitions( ReadRowDescription ) ) ]
30
35
ReadParameterDescription {
31
36
sender : mpsc:: UnboundedSender < Request > ,
32
37
receiver : mpsc:: Receiver < Message > ,
33
38
name : String ,
39
+ client : Client ,
34
40
} ,
35
41
#[ state_machine_future( transitions( ReadReadyForQuery ) ) ]
36
42
ReadRowDescription {
37
43
sender : mpsc:: UnboundedSender < Request > ,
38
44
receiver : mpsc:: Receiver < Message > ,
39
45
name : String ,
40
- parameters : ParameterDescriptionBody ,
46
+ parameters : Vec < Oid > ,
47
+ client : Client ,
41
48
} ,
42
- #[ state_machine_future( transitions( Finished ) ) ]
49
+ #[ state_machine_future( transitions( GetParameterTypes , GetColumnTypes , Finished ) ) ]
43
50
ReadReadyForQuery {
44
51
sender : mpsc:: UnboundedSender < Request > ,
45
52
receiver : mpsc:: Receiver < Message > ,
46
53
name : String ,
47
- parameters : ParameterDescriptionBody ,
48
- columns : Option < RowDescriptionBody > ,
54
+ parameters : Vec < Oid > ,
55
+ columns : Vec < ( String , Oid ) > ,
56
+ client : Client ,
57
+ } ,
58
+ #[ state_machine_future( transitions( GetColumnTypes , Finished ) ) ]
59
+ GetParameterTypes {
60
+ future : TypeinfoFuture ,
61
+ remaining_parameters : vec:: IntoIter < Oid > ,
62
+ sender : mpsc:: UnboundedSender < Request > ,
63
+ name : String ,
64
+ parameters : Vec < Type > ,
65
+ columns : Vec < ( String , Oid ) > ,
66
+ } ,
67
+ #[ state_machine_future( transitions( Finished ) ) ]
68
+ GetColumnTypes {
69
+ future : TypeinfoFuture ,
70
+ cur_column_name : String ,
71
+ remaining_columns : vec:: IntoIter < ( String , Oid ) > ,
72
+ sender : mpsc:: UnboundedSender < Request > ,
73
+ name : String ,
74
+ parameters : Vec < Type > ,
75
+ columns : Vec < Column > ,
49
76
} ,
50
77
#[ state_machine_future( ready) ]
51
78
Finished ( Statement ) ,
@@ -62,6 +89,7 @@ impl PollPrepare for Prepare {
62
89
sender: state. sender,
63
90
receiver,
64
91
name: state. name,
92
+ client: state. client,
65
93
} )
66
94
}
67
95
@@ -76,6 +104,7 @@ impl PollPrepare for Prepare {
76
104
sender: state. sender,
77
105
receiver: state. receiver,
78
106
name: state. name,
107
+ client: state. client,
79
108
} ) ,
80
109
Some ( Message :: ErrorResponse ( body) ) => Err ( error:: __db ( body) ) ,
81
110
Some ( _) => Err ( bad_response ( ) ) ,
@@ -94,7 +123,8 @@ impl PollPrepare for Prepare {
94
123
sender: state. sender,
95
124
receiver: state. receiver,
96
125
name: state. name,
97
- parameters: body,
126
+ parameters: body. parameters( ) . collect( ) ?,
127
+ client: state. client,
98
128
} ) ,
99
129
Some ( _) => Err ( bad_response ( ) ) ,
100
130
None => Err ( disconnected ( ) ) ,
@@ -107,9 +137,12 @@ impl PollPrepare for Prepare {
107
137
let message = try_receive ! ( state. receiver. poll( ) ) ;
108
138
let state = state. take ( ) ;
109
139
110
- let body = match message {
111
- Some ( Message :: RowDescription ( body) ) => Some ( body) ,
112
- Some ( Message :: NoData ) => None ,
140
+ let columns = match message {
141
+ Some ( Message :: RowDescription ( body) ) => body
142
+ . fields ( )
143
+ . map ( |f| ( f. name ( ) . to_string ( ) , f. type_oid ( ) ) )
144
+ . collect ( ) ?,
145
+ Some ( Message :: NoData ) => vec ! [ ] ,
113
146
Some ( _) => return Err ( bad_response ( ) ) ,
114
147
None => return Err ( disconnected ( ) ) ,
115
148
} ;
@@ -119,7 +152,8 @@ impl PollPrepare for Prepare {
119
152
receiver: state. receiver,
120
153
name: state. name,
121
154
parameters: state. parameters,
122
- columns: body,
155
+ columns,
156
+ client: state. client,
123
157
} )
124
158
}
125
159
@@ -130,33 +164,103 @@ impl PollPrepare for Prepare {
130
164
let state = state. take ( ) ;
131
165
132
166
match message {
133
- Some ( Message :: ReadyForQuery ( _) ) => {
134
- // FIXME handle custom types
135
- let parameters = state
136
- . parameters
137
- . parameters ( )
138
- . map ( |oid| Type :: from_oid ( oid) . unwrap ( ) )
139
- . collect ( ) ?;
140
- let columns = match state. columns {
141
- Some ( body) => body
142
- . fields ( )
143
- . map ( |f| {
144
- Column :: new ( f. name ( ) . to_string ( ) , Type :: from_oid ( f. type_oid ( ) ) . unwrap ( ) )
145
- } )
146
- . collect ( ) ?,
147
- None => vec ! [ ] ,
148
- } ;
149
-
150
- transition ! ( Finished ( Statement :: new(
151
- state. sender,
152
- state. name,
153
- parameters,
154
- columns
155
- ) ) )
167
+ Some ( Message :: ReadyForQuery ( _) ) => { }
168
+ Some ( _) => return Err ( bad_response ( ) ) ,
169
+ None => return Err ( disconnected ( ) ) ,
170
+ }
171
+
172
+ let mut parameters = state. parameters . into_iter ( ) ;
173
+ if let Some ( oid) = parameters. next ( ) {
174
+ transition ! ( GetParameterTypes {
175
+ future: TypeinfoFuture :: new( oid, state. client) ,
176
+ remaining_parameters: parameters,
177
+ sender: state. sender,
178
+ name: state. name,
179
+ parameters: vec![ ] ,
180
+ columns: state. columns,
181
+ } ) ;
182
+ }
183
+
184
+ let mut columns = state. columns . into_iter ( ) ;
185
+ if let Some ( ( name, oid) ) = columns. next ( ) {
186
+ transition ! ( GetColumnTypes {
187
+ future: TypeinfoFuture :: new( oid, state. client) ,
188
+ cur_column_name: name,
189
+ remaining_columns: columns,
190
+ sender: state. sender,
191
+ name: state. name,
192
+ parameters: vec![ ] ,
193
+ columns: vec![ ] ,
194
+ } ) ;
195
+ }
196
+
197
+ transition ! ( Finished ( Statement :: new(
198
+ state. sender,
199
+ state. name,
200
+ vec![ ] ,
201
+ vec![ ]
202
+ ) ) )
203
+ }
204
+
205
+ fn poll_get_parameter_types < ' a > (
206
+ state : & ' a mut RentToOwn < ' a , GetParameterTypes > ,
207
+ ) -> Poll < AfterGetParameterTypes , Error > {
208
+ let client = loop {
209
+ let ( ty, client) = try_ready ! ( state. future. poll( ) ) ;
210
+ state. parameters . push ( ty) ;
211
+
212
+ match state. remaining_parameters . next ( ) {
213
+ Some ( oid) => state. future = TypeinfoFuture :: new ( oid, client) ,
214
+ None => break client,
156
215
}
157
- Some ( _) => Err ( bad_response ( ) ) ,
158
- None => Err ( disconnected ( ) ) ,
216
+ } ;
217
+ let state = state. take ( ) ;
218
+
219
+ let mut columns = state. columns . into_iter ( ) ;
220
+ if let Some ( ( name, oid) ) = columns. next ( ) {
221
+ transition ! ( GetColumnTypes {
222
+ future: TypeinfoFuture :: new( oid, client) ,
223
+ cur_column_name: name,
224
+ remaining_columns: columns,
225
+ sender: state. sender,
226
+ name: state. name,
227
+ parameters: state. parameters,
228
+ columns: vec![ ] ,
229
+ } )
159
230
}
231
+
232
+ transition ! ( Finished ( Statement :: new(
233
+ state. sender,
234
+ state. name,
235
+ state. parameters,
236
+ vec![ ] ,
237
+ ) ) )
238
+ }
239
+
240
+ fn poll_get_column_types < ' a > (
241
+ state : & ' a mut RentToOwn < ' a , GetColumnTypes > ,
242
+ ) -> Poll < AfterGetColumnTypes , Error > {
243
+ loop {
244
+ let ( ty, client) = try_ready ! ( state. future. poll( ) ) ;
245
+ let name = mem:: replace ( & mut state. cur_column_name , String :: new ( ) ) ;
246
+ state. columns . push ( Column :: new ( name, ty) ) ;
247
+
248
+ match state. remaining_columns . next ( ) {
249
+ Some ( ( name, oid) ) => {
250
+ state. cur_column_name = name;
251
+ state. future = TypeinfoFuture :: new ( oid, client) ;
252
+ }
253
+ None => break ,
254
+ }
255
+ }
256
+ let state = state. take ( ) ;
257
+
258
+ transition ! ( Finished ( Statement :: new(
259
+ state. sender,
260
+ state. name,
261
+ state. parameters,
262
+ state. columns,
263
+ ) ) )
160
264
}
161
265
}
162
266
@@ -165,7 +269,8 @@ impl PrepareFuture {
165
269
request : PendingRequest ,
166
270
sender : mpsc:: UnboundedSender < Request > ,
167
271
name : String ,
272
+ client : Client ,
168
273
) -> PrepareFuture {
169
- Prepare :: start ( request, sender, name)
274
+ Prepare :: start ( request, sender, name, client )
170
275
}
171
276
}
0 commit comments