2222import java .sql .SQLException ;
2323import java .util .HashMap ;
2424import java .util .Map ;
25- import java .util .UUID ;
2625import java .util .function .Function ;
2726import javax .net .ssl .SSLHandshakeException ;
2827import org .apache .ignite .client .IgniteClientConnectionException ;
2928import org .apache .ignite .internal .cli .core .exception .ExceptionHandler ;
3029import org .apache .ignite .internal .cli .core .exception .ExceptionWriter ;
3130import org .apache .ignite .internal .cli .core .style .component .ErrorUiComponent ;
32- import org .apache .ignite .internal .cli .core .style .component .ErrorUiComponent .ErrorComponentBuilder ;
33- import org .apache .ignite .internal .jdbc .proto .SqlStateCode ;
3431import org .apache .ignite .internal .logger .IgniteLogger ;
3532import org .apache .ignite .internal .logger .Loggers ;
3633import org .apache .ignite .internal .util .ExceptionUtils ;
@@ -49,33 +46,23 @@ public class SqlExceptionHandler implements ExceptionHandler<SQLException> {
4946
5047 private static final IgniteLogger LOG = Loggers .forClass (SqlExceptionHandler .class );
5148
52- public static final String PARSING_ERROR_MESSAGE = "SQL query parsing error " ;
49+ private static final String CLIENT_CONNECTION_FAILED_MESSAGE = "Connection failed " ;
5350
54- public static final String INVALID_PARAMETER_MESSAGE = "Invalid parameter value " ;
51+ private static final String UNRECOGNIZED_ERROR_MESSAGE = "Unrecognized error while processing SQL query " ;
5552
56- public static final String CLIENT_CONNECTION_FAILED_MESSAGE = "Connection failed" ;
57-
58- public static final String CONNECTION_BROKE_MESSAGE = "Connection error" ;
59-
60- public static final String UNRECOGNIZED_ERROR_MESSAGE = "Unrecognized error while processing SQL query " ;
61-
62- private final Map <Integer , Function <IgniteException , ErrorComponentBuilder >> sqlExceptionMappers = new HashMap <>();
53+ private final Map <Short , Function <IgniteException , ErrorUiComponent >> sqlExceptionMappers = new HashMap <>();
6354
6455 /** Default constructor. */
6556 private SqlExceptionHandler () {
66- sqlExceptionMappers .put (Client .CONNECTION_ERR , SqlExceptionHandler ::connectionErrUiComponent );
67- sqlExceptionMappers .put (Sql .STMT_PARSE_ERR , SqlExceptionHandler ::sqlParseErrUiComponent );
57+ sqlExceptionMappers .put (Client .CLIENT_ERR_GROUP . groupCode () , SqlExceptionHandler ::connectionErrUiComponent );
58+ sqlExceptionMappers .put (Sql .SQL_ERR_GROUP . groupCode () , SqlExceptionHandler ::sqlErrUiComponent );
6859 }
6960
70- private static ErrorComponentBuilder sqlParseErrUiComponent (IgniteException e ) {
71- return fromExWithHeader (PARSING_ERROR_MESSAGE , e .code (), e .traceId (), e .getMessage ());
72- }
73-
74- private static ErrorComponentBuilder unrecognizedErrComponent (IgniteException e ) {
75- return fromExWithHeader (UNRECOGNIZED_ERROR_MESSAGE , e .code (), e .traceId (), e .getMessage ());
76- }
61+ private static ErrorUiComponent connectionErrUiComponent (IgniteException e ) {
62+ if (e .code () != Client .CONNECTION_ERR ) {
63+ return fromIgniteException ("Client error" , e );
64+ }
7765
78- private static ErrorComponentBuilder connectionErrUiComponent (IgniteException e ) {
7966 if (e .getCause () instanceof IgniteClientConnectionException ) {
8067 IgniteClientConnectionException cause = (IgniteClientConnectionException ) e .getCause ();
8168
@@ -84,21 +71,23 @@ private static ErrorComponentBuilder connectionErrUiComponent(IgniteException e)
8471 return ErrorUiComponent .builder ()
8572 .header ("Could not connect to node. Check authentication configuration" )
8673 .details (invalidCredentialsException .getMessage ())
87- .verbose (extractCauseMessage (cause .getMessage ()));
74+ .verbose (extractCauseMessage (cause .getMessage ()))
75+ .build ();
8876 }
8977
9078 SSLHandshakeException sslHandshakeException = findCause (cause , SSLHandshakeException .class );
9179 if (sslHandshakeException != null ) {
9280 return ErrorUiComponent .builder ()
9381 .header ("Could not connect to node. Check SSL configuration" )
9482 .details (sslHandshakeException .getMessage ())
95- .verbose (extractCauseMessage (cause .getMessage ()));
83+ .verbose (extractCauseMessage (cause .getMessage ()))
84+ .build ();
9685 }
9786
98- return fromExWithHeader (CLIENT_CONNECTION_FAILED_MESSAGE , cause . code (), cause . traceId (), cause . getMessage () );
87+ return fromIgniteException (CLIENT_CONNECTION_FAILED_MESSAGE , cause );
9988 }
10089
101- return fromExWithHeader (CLIENT_CONNECTION_FAILED_MESSAGE , e . code (), e . traceId (), e . getMessage () );
90+ return fromIgniteException (CLIENT_CONNECTION_FAILED_MESSAGE , e );
10291 }
10392
10493 @ Nullable
@@ -112,67 +101,86 @@ private static <T extends Throwable> T findCause(Throwable e, Class<T> type) {
112101 return null ;
113102 }
114103
115- private static ErrorComponentBuilder fromExWithHeader (String header , int errorCode , UUID traceId , String message ) {
116- return ErrorUiComponent .builder ()
117- .header (header )
118- .errorCode (String .valueOf (errorCode ))
119- .traceId (traceId )
120- .details (extractCauseMessage (message ));
121- }
122-
123104 @ Override
124105 public int handle (ExceptionWriter err , SQLException e ) {
125106 Throwable unwrappedCause = ExceptionUtils .unwrapCause (e .getCause ());
107+ ErrorUiComponent errorComponent ;
108+
126109 if (unwrappedCause instanceof IgniteException ) {
127- return handleIgniteException (err , (IgniteException ) unwrappedCause );
128- }
110+ IgniteException igniteException = (IgniteException ) unwrappedCause ;
129111
130- if (unwrappedCause instanceof IgniteCheckedException ) {
131- return handleIgniteCheckedException (err , (IgniteCheckedException ) unwrappedCause );
132- }
112+ errorComponent = sqlExceptionMappers .getOrDefault (
113+ igniteException .groupCode (),
114+ SqlExceptionHandler ::otherIgniteException
115+ ).apply (igniteException );
116+
117+ } else if (unwrappedCause instanceof IgniteCheckedException ) {
118+ IgniteCheckedException checkedError = (IgniteCheckedException ) unwrappedCause ;
119+
120+ errorComponent = fromCheckedIgniteException (UNRECOGNIZED_ERROR_MESSAGE , checkedError );
121+ } else {
122+ LOG .warn ("Unrecognized exception" , e );
133123
134- var errorComponentBuilder = ErrorUiComponent .builder ();
135-
136- switch (e .getSQLState ()) {
137- case SqlStateCode .CONNECTION_FAILURE :
138- case SqlStateCode .CONNECTION_CLOSED :
139- case SqlStateCode .CONNECTION_REJECTED :
140- errorComponentBuilder .header (CONNECTION_BROKE_MESSAGE ).verbose (extractCauseMessage (e .getMessage ()));
141- break ;
142- case SqlStateCode .PARSING_EXCEPTION :
143- errorComponentBuilder .header (PARSING_ERROR_MESSAGE ).details (extractCauseMessage (e .getMessage ()));
144- break ;
145- case SqlStateCode .INVALID_PARAMETER_VALUE :
146- errorComponentBuilder .header (INVALID_PARAMETER_MESSAGE ).verbose (extractCauseMessage (e .getMessage ()));
147- break ;
148- case SqlStateCode .CLIENT_CONNECTION_FAILED :
149- errorComponentBuilder .header (CLIENT_CONNECTION_FAILED_MESSAGE ).verbose (extractCauseMessage (e .getMessage ()));
150- break ;
151- default :
152- LOG .error ("Unrecognized error" , e );
153- errorComponentBuilder .header ("SQL query execution error" ).details (e .getMessage ());
124+ errorComponent = ErrorUiComponent .builder ()
125+ .header ("Unrecognized exception" )
126+ .details (String .valueOf (unwrappedCause ))
127+ .build ();
154128 }
155129
156- err .write (errorComponentBuilder . build () .render ());
130+ err .write (errorComponent .render ());
157131 return 1 ;
158132 }
159133
160- /** Handles IgniteException that has more information like error code and trace id. */
161- private int handleIgniteException (ExceptionWriter err , IgniteException e ) {
162- var errorComponentBuilder = sqlExceptionMappers .getOrDefault (e .code (), SqlExceptionHandler ::unrecognizedErrComponent );
134+ private static ErrorUiComponent sqlErrUiComponent (IgniteException e ) {
135+ String header ;
136+
137+ if (e .code () == Sql .STMT_PARSE_ERR ) {
138+ header = "SQL query parsing error" ;
139+ } else if (e .code () == Sql .STMT_VALIDATION_ERR ) {
140+ header = "SQL query validation error" ;
141+ } else if (e .code () == Sql .CONSTRAINT_VIOLATION_ERR ) {
142+ header = "Constraint violation" ;
143+ } else if (e .code () == Sql .EXECUTION_CANCELLED_ERR ) {
144+ header = "Query was cancelled" ;
145+ } else if (e .code () == Sql .RUNTIME_ERR ) {
146+ header = "SQL query execution error" ;
147+ } else if (e .code () == Sql .MAPPING_ERR ) {
148+ header = "Unable to map query on current cluster topology" ;
149+ } else if (e .code () == Sql .TX_CONTROL_INSIDE_EXTERNAL_TX_ERR ) {
150+ header = "Unexpected SQL statement" ;
151+ } else {
152+ header = "SQL error" ;
153+ }
163154
164- String renderedError = errorComponentBuilder . apply ( e ). build (). render ( );
165- err . write ( renderedError );
155+ return fromIgniteException ( header , e );
156+ }
166157
167- return 1 ;
158+ private static ErrorUiComponent fromIgniteException (String header , IgniteException e ) {
159+ // Header
160+ // GROUP_NAME-CODE: ...
161+ return ErrorUiComponent .builder ()
162+ .header (header )
163+ .errorCode (String .valueOf (e .code ()))
164+ .traceId (e .traceId ())
165+ .details (e .codeAsString () + ": " + extractCauseMessage (e .getMessage ()))
166+ .build ();
168167 }
169168
170- private static int handleIgniteCheckedException (ExceptionWriter err , IgniteCheckedException e ) {
171- String renderedError = fromExWithHeader (UNRECOGNIZED_ERROR_MESSAGE , e .code (), e .traceId (), e .getMessage ())
172- .build ().render ();
173- err .write (renderedError );
169+ private static ErrorUiComponent fromCheckedIgniteException (String header , IgniteCheckedException e ) {
170+ // Header
171+ // GROUP_NAME-CODE: ...
172+ return ErrorUiComponent .builder ()
173+ .header (header )
174+ .errorCode (String .valueOf (e .code ()))
175+ .traceId (e .traceId ())
176+ .details (e .codeAsString () + ": " + extractCauseMessage (e .getMessage ()))
177+ .build ();
178+ }
174179
175- return 1 ;
180+ private static ErrorUiComponent otherIgniteException (IgniteException e ) {
181+ // GROUP_NAME error
182+ // GROUP_NAME-CODE: ...
183+ return fromIgniteException (e .groupName () + " error" , e );
176184 }
177185
178186 @ Override
0 commit comments