This is an automated email from the ASF dual-hosted git repository.

mpochatkin pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git


The following commit(s) were added to refs/heads/main by this push:
     new ac2de38dbeb IGNITE-27127 NPE in CLI SQL (#7032)
ac2de38dbeb is described below

commit ac2de38dbebe11ed9ae0703789b7155c68ecb85b
Author: Vadim Pakhnushev <[email protected]>
AuthorDate: Fri Nov 21 15:41:20 2025 +0300

    IGNITE-27127 NPE in CLI SQL (#7032)
---
 .../exception/handler/SqlExceptionHandler.java     | 49 +++++++++++++---------
 .../cli/core/style/component/ErrorUiComponent.java | 18 ++++----
 2 files changed, 38 insertions(+), 29 deletions(-)

diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/SqlExceptionHandler.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/SqlExceptionHandler.java
index f3dc69c3584..ab61d40fbb9 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/SqlExceptionHandler.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/SqlExceptionHandler.java
@@ -75,6 +75,10 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
         return fromExWithHeader(UNRECOGNIZED_ERROR_MESSAGE, e.code(), 
e.traceId(), e.getMessage());
     }
 
+    private static ErrorComponentBuilder 
unrecognizedErrComponent(IgniteCheckedException e) {
+        return fromExWithHeader(UNRECOGNIZED_ERROR_MESSAGE, e.code(), 
e.traceId(), e.getMessage());
+    }
+
     private static ErrorComponentBuilder 
connectionErrUiComponent(IgniteException e) {
         if (e.getCause() instanceof IgniteClientConnectionException) {
             IgniteClientConnectionException cause = 
(IgniteClientConnectionException) e.getCause();
@@ -122,16 +126,29 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
 
     @Override
     public int handle(ExceptionWriter err, SQLException e) {
+        err.write(handleSqlException(e).build().render());
+        return 1;
+    }
+
+    private ErrorComponentBuilder handleSqlException(SQLException e) {
         Throwable unwrappedCause = ExceptionUtils.unwrapCause(e.getCause());
         if (unwrappedCause instanceof IgniteException) {
-            return handleIgniteException(err, (IgniteException) 
unwrappedCause);
+            return handleIgniteException((IgniteException) unwrappedCause);
         }
 
         if (unwrappedCause instanceof IgniteCheckedException) {
-            return handleIgniteCheckedException(err, (IgniteCheckedException) 
unwrappedCause);
+            return unrecognizedErrComponent((IgniteCheckedException) 
unwrappedCause);
+        }
+
+        if (e.getSQLState() != null) {
+            return handleExceptionWithState(e);
         }
 
-        var errorComponentBuilder = ErrorUiComponent.builder();
+        return handleUnrecognizedError(e);
+    }
+
+    private static ErrorComponentBuilder handleExceptionWithState(SQLException 
e) {
+        ErrorComponentBuilder errorComponentBuilder = 
ErrorUiComponent.builder();
 
         switch (e.getSQLState()) {
             case SqlStateCode.CONNECTION_FAILURE:
@@ -149,30 +166,22 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
                 
errorComponentBuilder.header(CLIENT_CONNECTION_FAILED_MESSAGE).verbose(extractCauseMessage(e.getMessage()));
                 break;
             default:
-                LOG.error("Unrecognized error", e);
-                errorComponentBuilder.header("SQL query execution 
error").details(e.getMessage());
+                return handleUnrecognizedError(e);
         }
 
-        err.write(errorComponentBuilder.build().render());
-        return 1;
+        return errorComponentBuilder;
     }
 
-    /** Handles IgniteException that has more information like error code and 
trace id. */
-    private int handleIgniteException(ExceptionWriter err, IgniteException e) {
-        var errorComponentBuilder = sqlExceptionMappers.getOrDefault(e.code(), 
SqlExceptionHandler::unrecognizedErrComponent);
-
-        String renderedError = errorComponentBuilder.apply(e).build().render();
-        err.write(renderedError);
-
-        return 1;
+    private static ErrorComponentBuilder handleUnrecognizedError(SQLException 
e) {
+        LOG.error("Unrecognized error", e);
+        return ErrorUiComponent.builder().header("SQL query execution 
error").details(e.getMessage());
     }
 
-    private static int handleIgniteCheckedException(ExceptionWriter err, 
IgniteCheckedException e) {
-        String renderedError = fromExWithHeader(UNRECOGNIZED_ERROR_MESSAGE, 
e.code(), e.traceId(), e.getMessage())
-                .build().render();
-        err.write(renderedError);
+    /** Handles IgniteException that has more information like error code and 
trace id. */
+    private ErrorComponentBuilder handleIgniteException(IgniteException e) {
+        var exceptionMapper = sqlExceptionMappers.getOrDefault(e.code(), 
SqlExceptionHandler::unrecognizedErrComponent);
 
-        return 1;
+        return exceptionMapper.apply(e);
     }
 
     @Override
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/style/component/ErrorUiComponent.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/style/component/ErrorUiComponent.java
index 0db1f0d6ffe..3325f0b28f1 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/style/component/ErrorUiComponent.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/style/component/ErrorUiComponent.java
@@ -26,6 +26,7 @@ import 
org.apache.ignite.internal.cli.core.style.AnsiStringSupport.Style;
 import org.apache.ignite.internal.cli.core.style.element.UiElement;
 import org.apache.ignite.internal.cli.core.style.element.UiString;
 import org.apache.ignite.internal.cli.logger.CliLoggers;
+import org.jetbrains.annotations.Nullable;
 
 /**
  * UI component that represent any error message.
@@ -49,10 +50,11 @@ public class ErrorUiComponent implements UiComponent {
 
     private ErrorUiComponent(
             String header, UiElement[] headerUiElements,
-            String details, UiElement[] detailsUiElements,
-            String verbose, UiElement[] verboseUiElements,
+            @Nullable String details, UiElement[] detailsUiElements,
+            @Nullable String verbose, UiElement[] verboseUiElements,
             UUID traceId,
-            String errorCode) {
+            String errorCode
+    ) {
         this.header = header;
         this.headerUiElements = headerUiElements;
         this.details = details;
@@ -77,10 +79,6 @@ public class ErrorUiComponent implements UiComponent {
         return header;
     }
 
-    public String details() {
-        return details;
-    }
-
     @Override
     public String render() {
         return ansi(renderErrorCode() + renderTrace() + renderHeader() + 
renderDetails() + renderVerbose());
@@ -112,10 +110,12 @@ public class ErrorUiComponent implements UiComponent {
 
         private UiElement[] headerUiElements;
 
+        @Nullable
         private String details;
 
         private UiElement[] detailsUiElements;
 
+        @Nullable
         private String verbose;
 
         private UiElement[] verboseUiElements;
@@ -132,7 +132,7 @@ public class ErrorUiComponent implements UiComponent {
         }
 
         /** Sets details. */
-        public ErrorComponentBuilder details(String details, UiElement... 
uiElements) {
+        public ErrorComponentBuilder details(@Nullable String details, 
UiElement... uiElements) {
             this.details = details;
             this.detailsUiElements = uiElements;
             return this;
@@ -144,7 +144,7 @@ public class ErrorUiComponent implements UiComponent {
         }
 
         /** Sets verbose. */
-        public ErrorComponentBuilder verbose(String verbose, UiElement... 
uiElements) {
+        public ErrorComponentBuilder verbose(@Nullable String verbose, 
UiElement... uiElements) {
             this.verbose = verbose;
             this.verboseUiElements = uiElements;
             return this;

Reply via email to