@@ -18,6 +18,7 @@ use crate::compression::lz4::Lz4Decoder;
1818use crate :: {
1919 compression:: Compression ,
2020 error:: { Error , Result } ,
21+ query_summary:: QuerySummary ,
2122} ;
2223
2324// === Response ===
@@ -30,7 +31,8 @@ pub(crate) enum Response {
3031 Loading ( Chunks ) ,
3132}
3233
33- pub ( crate ) type ResponseFuture = Pin < Box < dyn Future < Output = Result < Chunks > > + Send > > ;
34+ pub ( crate ) type ResponseFuture =
35+ Pin < Box < dyn Future < Output = Result < ( Chunks , Option < Box < QuerySummary > > ) > > + Send > > ;
3436
3537impl Response {
3638 pub ( crate ) fn new ( response : HyperResponseFuture , compression : Compression ) -> Self {
@@ -46,9 +48,16 @@ impl Response {
4648 . get ( "X-ClickHouse-Exception-Tag" )
4749 . map ( |value| value. as_bytes ( ) . into ( ) ) ;
4850
51+ let summary = response
52+ . headers ( )
53+ . get ( "X-ClickHouse-Summary" )
54+ . and_then ( |v| v. to_str ( ) . ok ( ) )
55+ . and_then ( QuerySummary :: from_header)
56+ . map ( Box :: new) ;
57+
4958 // More likely to be successful, start streaming.
5059 // It still can fail, but we'll handle it in `DetectDbException`.
51- Ok ( Chunks :: new ( response. into_body ( ) , compression, tag) )
60+ Ok ( ( Chunks :: new ( response. into_body ( ) , compression, tag) , summary ) )
5261 } else {
5362 // An instantly failed request.
5463 Err ( collect_bad_response (
@@ -74,7 +83,10 @@ impl Response {
7483 pub ( crate ) async fn finish ( & mut self ) -> Result < ( ) > {
7584 let chunks = loop {
7685 match self {
77- Self :: Waiting ( future) => * self = Self :: Loading ( future. await ?) ,
86+ Self :: Waiting ( future) => {
87+ let ( chunks, _summary) = future. await ?;
88+ * self = Self :: Loading ( chunks) ;
89+ }
7890 Self :: Loading ( chunks) => break chunks,
7991 }
8092 } ;
@@ -157,7 +169,9 @@ pub(crate) struct Chunk {
157169
158170// * Uses `Option<_>` to make this stream fused.
159171// * Uses `Box<_>` in order to reduce the size of cursors.
160- pub ( crate ) struct Chunks ( Option < Box < DetectDbException < Decompress < IncomingStream > > > > ) ;
172+ pub ( crate ) struct Chunks {
173+ inner : Option < Box < DetectDbException < Decompress < IncomingStream > > > > ,
174+ }
161175
162176impl Chunks {
163177 fn new ( stream : Incoming , compression : Compression , exception_tag : Option < Box < [ u8 ] > > ) -> Self {
@@ -167,16 +181,18 @@ impl Chunks {
167181 stream,
168182 exception_tag,
169183 } ;
170- Self ( Some ( Box :: new ( stream) ) )
184+ Self {
185+ inner : Some ( Box :: new ( stream) ) ,
186+ }
171187 }
172188
173189 pub ( crate ) fn empty ( ) -> Self {
174- Self ( None )
190+ Self { inner : None }
175191 }
176192
177193 #[ cfg( feature = "futures03" ) ]
178194 pub ( crate ) fn is_terminated ( & self ) -> bool {
179- self . 0 . is_none ( )
195+ self . inner . is_none ( )
180196 }
181197}
182198
@@ -185,11 +201,11 @@ impl Stream for Chunks {
185201
186202 fn poll_next ( mut self : Pin < & mut Self > , cx : & mut Context < ' _ > ) -> Poll < Option < Self :: Item > > {
187203 // We use `take()` to make the stream fused, including the case of panics.
188- if let Some ( mut stream) = self . 0 . take ( ) {
204+ if let Some ( mut stream) = self . inner . take ( ) {
189205 let res = Pin :: new ( & mut stream) . poll_next ( cx) ;
190206
191207 if matches ! ( res, Poll :: Pending | Poll :: Ready ( Some ( Ok ( _) ) ) ) {
192- self . 0 = Some ( stream) ;
208+ self . inner = Some ( stream) ;
193209 }
194210
195211 res
0 commit comments