1
1
use std:: sync:: Arc ;
2
2
3
+ use futures_core:: future:: BoxFuture ;
3
4
use futures_core:: Stream ;
4
5
use futures_option:: OptionExt ;
5
6
use prost:: Message ;
@@ -11,6 +12,7 @@ use tonic::{Code, Status};
11
12
12
13
use crate :: auth:: Authenticated ;
13
14
use crate :: connection:: Connection ;
15
+ use crate :: connection:: program:: Program ;
14
16
use crate :: error:: Error ;
15
17
use crate :: query_analysis:: TxnStatus ;
16
18
use crate :: query_result_builder:: {
@@ -19,6 +21,7 @@ use crate::query_result_builder::{
19
21
use crate :: replication:: FrameNo ;
20
22
use crate :: rpc:: proxy:: rpc:: exec_req:: Request ;
21
23
use crate :: rpc:: proxy:: rpc:: exec_resp:: { self , Response } ;
24
+ use crate :: rpc:: proxy:: rpc:: { DescribeResp , StreamDescribeReq , DescribeCol , DescribeParam } ;
22
25
23
26
use super :: proxy:: rpc:: resp_step:: Step ;
24
27
use super :: proxy:: rpc:: row_value:: Value ;
52
55
C : Connection ,
53
56
{
54
57
async_stream:: stream! {
55
- let mut current_request_fut = None ;
58
+ let mut current_request_fut: Option < BoxFuture < ' static , ( crate :: Result < ( ) > , u32 ) >> = None ;
56
59
let ( snd, mut recv) = mpsc:: channel( 1 ) ;
57
60
let conn = Arc :: new( conn) ;
58
61
@@ -90,13 +93,41 @@ where
90
93
max_program_resp_size,
91
94
} ;
92
95
93
- let ret = conn. execute_program( pgm, auth, builder, None ) . await ;
96
+ let ret = conn. execute_program( pgm, auth, builder, None ) . await . map ( |_| ( ) ) ;
94
97
( ret, request_id)
95
98
} ;
96
99
97
100
current_request_fut. replace( Box :: pin( fut) ) ;
98
101
}
99
- Some ( Request :: Describe ( _) ) => todo!( ) ,
102
+ Some ( Request :: Describe ( StreamDescribeReq { stmt } ) ) => {
103
+ let auth = auth. clone( ) ;
104
+ let sender = snd. clone( ) ;
105
+ let conn = conn. clone( ) ;
106
+ let fut = async move {
107
+ let do_describe = || async move {
108
+ let ret = conn. describe( stmt, auth, None ) . await ??;
109
+ Ok ( DescribeResp {
110
+ cols: ret. cols. into_iter( ) . map( |c| DescribeCol { name: c. name, decltype: c. decltype } ) . collect( ) ,
111
+ params: ret. params. into_iter( ) . map( |p| DescribeParam { name: p. name } ) . collect( ) ,
112
+ is_explain: ret. is_explain,
113
+ is_readonly: ret. is_readonly
114
+ } )
115
+ } ;
116
+
117
+ let ret: crate :: Result <( ) > = match do_describe( ) . await {
118
+ Ok ( resp) => {
119
+ let _ = sender. send( ExecResp { request_id, response: Some ( Response :: DescribeResp ( resp) ) } ) . await ;
120
+ Ok ( ( ) )
121
+ }
122
+ Err ( e) => Err ( e) ,
123
+ } ;
124
+
125
+ ( ret, request_id)
126
+ } ;
127
+
128
+ current_request_fut. replace( Box :: pin( fut) ) ;
129
+
130
+ } ,
100
131
None => {
101
132
yield Err ( Status :: new( Code :: InvalidArgument , "invalid request" ) ) ;
102
133
break
@@ -414,7 +445,7 @@ mod test {
414
445
namespace : None ,
415
446
permission : Permission :: FullAccess ,
416
447
} ) ;
417
- // limit the size of the response for force a split
448
+ // limit the size of the response to force a split
418
449
let stream = make_proxy_stream_inner ( conn, auth, ReceiverStream :: new ( rcv) , 500 ) ;
419
450
420
451
pin ! ( stream) ;
@@ -470,8 +501,7 @@ mod test {
470
501
namespace : None ,
471
502
permission : Permission :: FullAccess ,
472
503
} ) ;
473
- // limit the size of the response for force a split
474
- let stream = make_proxy_stream_inner ( conn, auth, ReceiverStream :: new ( rcv) , 500 ) ;
504
+ let stream = make_proxy_stream ( conn, auth, ReceiverStream :: new ( rcv) ) ;
475
505
476
506
pin ! ( stream) ;
477
507
@@ -526,8 +556,7 @@ mod test {
526
556
namespace : None ,
527
557
permission : Permission :: FullAccess ,
528
558
} ) ;
529
- // limit the size of the response for force a split
530
- let stream = make_proxy_stream_inner ( conn, auth, ReceiverStream :: new ( rcv) , 500 ) ;
559
+ let stream = make_proxy_stream ( conn, auth, ReceiverStream :: new ( rcv) ) ;
531
560
532
561
pin ! ( stream) ;
533
562
@@ -540,4 +569,28 @@ mod test {
540
569
let resp = stream. next ( ) . await . unwrap ( ) . unwrap ( ) ;
541
570
assert_eq ! ( resp. request_id, 1 ) ;
542
571
}
572
+
573
+ #[ tokio:: test]
574
+ async fn describe ( ) {
575
+ let tmp = tempdir ( ) . unwrap ( ) ;
576
+ let conn = LibSqlConnection :: new_test ( tmp. path ( ) ) ;
577
+ let ( snd, rcv) = mpsc:: channel ( 1 ) ;
578
+ let auth = Authenticated :: Authorized ( Authorized {
579
+ namespace : None ,
580
+ permission : Permission :: FullAccess ,
581
+ } ) ;
582
+ let stream = make_proxy_stream ( conn, auth, ReceiverStream :: new ( rcv) ) ;
583
+
584
+ pin ! ( stream) ;
585
+
586
+ // request 0 should be dropped, and request 1 should be processed instead
587
+ let req = ExecReq {
588
+ request_id : 0 ,
589
+ request : Some ( Request :: Describe ( StreamDescribeReq { stmt : "select $hello" . into ( ) } ) ) ,
590
+ } ;
591
+
592
+ snd. send ( Ok ( req) ) . await . unwrap ( ) ;
593
+
594
+ assert_debug_snapshot ! ( stream. next( ) . await . unwrap( ) . unwrap( ) ) ;
595
+ }
543
596
}
0 commit comments