@@ -22,6 +22,7 @@ use crate::{
2222 transport:: { MetaContext , SpanId } ,
2323 CubeError ,
2424} ;
25+ use datafusion:: { arrow:: error:: ArrowError , error:: DataFusionError } ;
2526use futures:: { FutureExt , StreamExt } ;
2627use log:: { debug, error, trace} ;
2728use pg_srv:: {
@@ -108,6 +109,10 @@ impl QueryPlanExt for QueryPlan {
108109pub enum ConnectionError {
109110 #[ error( "CubeError: {0}" ) ]
110111 Cube ( CubeError , Option < Arc < SpanId > > ) ,
112+ #[ error( "DataFusionError: {0}" ) ]
113+ DataFusion ( DataFusionError , Option < Arc < SpanId > > ) ,
114+ #[ error( "ArrowError: {0}" ) ]
115+ Arrow ( ArrowError , Option < Arc < SpanId > > ) ,
111116 #[ error( "CompilationError: {0}" ) ]
112117 CompilationError ( CompilationError , Option < Arc < SpanId > > ) ,
113118 #[ error( "ProtocolError: {0}" ) ]
@@ -121,15 +126,16 @@ impl ConnectionError {
121126 ConnectionError :: Cube ( e, _) => e. backtrace ( ) ,
122127 ConnectionError :: CompilationError ( e, _) => e. backtrace ( ) ,
123128 ConnectionError :: Protocol ( e, _) => e. backtrace ( ) ,
129+ ConnectionError :: DataFusion ( _, _) | ConnectionError :: Arrow ( _, _) => None ,
124130 }
125131 }
126132
127133 /// Converts Error to protocol::ErrorResponse which is usefully for writing response to the client
128134 pub fn to_error_response ( self ) -> protocol:: ErrorResponse {
129135 match self {
130- ConnectionError :: Cube ( e, _) => {
131- protocol :: ErrorResponse :: error ( protocol :: ErrorCode :: InternalError , e . to_string ( ) )
132- }
136+ ConnectionError :: Cube ( e, _) => Self :: cube_to_error_response ( & e ) ,
137+ ConnectionError :: DataFusion ( e , _ ) => Self :: df_to_error_response ( & e ) ,
138+ ConnectionError :: Arrow ( e , _ ) => Self :: arrow_to_error_response ( & e ) ,
133139 ConnectionError :: CompilationError ( e, _) => {
134140 fn to_error_response ( e : CompilationError ) -> protocol:: ErrorResponse {
135141 match e {
@@ -161,6 +167,8 @@ impl ConnectionError {
161167 pub fn with_span_id ( self , span_id : Option < Arc < SpanId > > ) -> Self {
162168 match self {
163169 ConnectionError :: Cube ( e, _) => ConnectionError :: Cube ( e, span_id) ,
170+ ConnectionError :: DataFusion ( e, _) => ConnectionError :: DataFusion ( e, span_id) ,
171+ ConnectionError :: Arrow ( e, _) => ConnectionError :: Arrow ( e, span_id) ,
164172 ConnectionError :: CompilationError ( e, _) => {
165173 ConnectionError :: CompilationError ( e, span_id)
166174 }
@@ -171,10 +179,59 @@ impl ConnectionError {
171179 pub fn span_id ( & self ) -> Option < Arc < SpanId > > {
172180 match self {
173181 ConnectionError :: Cube ( _, span_id) => span_id. clone ( ) ,
182+ ConnectionError :: DataFusion ( _, span_id) => span_id. clone ( ) ,
183+ ConnectionError :: Arrow ( _, span_id) => span_id. clone ( ) ,
174184 ConnectionError :: CompilationError ( _, span_id) => span_id. clone ( ) ,
175185 ConnectionError :: Protocol ( _, span_id) => span_id. clone ( ) ,
176186 }
177187 }
188+
189+ fn cube_to_error_response ( e : & CubeError ) -> protocol:: ErrorResponse {
190+ let message = e. to_string ( ) ;
191+ // Remove `Error: ` prefix that can come from JS
192+ let message = if let Some ( message) = message. strip_prefix ( "Error: " ) {
193+ message. to_string ( )
194+ } else {
195+ message
196+ } ;
197+ protocol:: ErrorResponse :: error ( protocol:: ErrorCode :: InternalError , message)
198+ }
199+
200+ fn df_to_error_response ( e : & DataFusionError ) -> protocol:: ErrorResponse {
201+ match e {
202+ DataFusionError :: ArrowError ( arrow_err) => {
203+ return Self :: arrow_to_error_response ( arrow_err) ;
204+ }
205+ DataFusionError :: External ( err) => {
206+ if let Some ( cube_err) = err. downcast_ref :: < CubeError > ( ) {
207+ return Self :: cube_to_error_response ( cube_err) ;
208+ }
209+ }
210+ _ => { }
211+ }
212+ protocol:: ErrorResponse :: error (
213+ protocol:: ErrorCode :: InternalError ,
214+ format ! ( "Post-processing Error: {}" , e) ,
215+ )
216+ }
217+
218+ fn arrow_to_error_response ( e : & ArrowError ) -> protocol:: ErrorResponse {
219+ match e {
220+ ArrowError :: ExternalError ( err) => {
221+ if let Some ( df_err) = err. downcast_ref :: < DataFusionError > ( ) {
222+ return Self :: df_to_error_response ( df_err) ;
223+ }
224+ if let Some ( cube_err) = err. downcast_ref :: < CubeError > ( ) {
225+ return Self :: cube_to_error_response ( cube_err) ;
226+ }
227+ }
228+ _ => { }
229+ }
230+ protocol:: ErrorResponse :: error (
231+ protocol:: ErrorCode :: InternalError ,
232+ format ! ( "Post-processing Error: {}" , e) ,
233+ )
234+ }
178235}
179236
180237impl From < CubeError > for ConnectionError {
@@ -201,15 +258,15 @@ impl From<tokio::task::JoinError> for ConnectionError {
201258 }
202259}
203260
204- impl From < datafusion :: error :: DataFusionError > for ConnectionError {
205- fn from ( e : datafusion :: error :: DataFusionError ) -> Self {
206- ConnectionError :: Cube ( e . into ( ) , None )
261+ impl From < DataFusionError > for ConnectionError {
262+ fn from ( e : DataFusionError ) -> Self {
263+ ConnectionError :: DataFusion ( e , None )
207264 }
208265}
209266
210- impl From < datafusion :: arrow :: error :: ArrowError > for ConnectionError {
211- fn from ( e : datafusion :: arrow :: error :: ArrowError ) -> Self {
212- ConnectionError :: Cube ( e . into ( ) , None )
267+ impl From < ArrowError > for ConnectionError {
268+ fn from ( e : ArrowError ) -> Self {
269+ ConnectionError :: Arrow ( e , None )
213270 }
214271}
215272
@@ -1904,3 +1961,13 @@ impl AsyncPostgresShim {
19041961 . ok_or ( CubeError :: internal ( "must be auth" . to_string ( ) ) )
19051962 }
19061963}
1964+
1965+ #[ cfg( test) ]
1966+ mod tests {
1967+ use super :: * ;
1968+
1969+ #[ test]
1970+ fn test_connection_error_mem_size ( ) {
1971+ assert_eq ! ( std:: mem:: size_of:: <ConnectionError >( ) , 136 )
1972+ }
1973+ }
0 commit comments