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

sk0x50 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 eb4f324245 IGNITE-17090 Show user-friendly message in sql command. 
Fixes #1024
eb4f324245 is described below

commit eb4f324245054187b562baba5e3e5f7ed17ce90f
Author: Aleksandr Pakhomov <[email protected]>
AuthorDate: Fri Sep 9 19:57:43 2022 +0300

    IGNITE-17090 Show user-friendly message in sql command. Fixes #1024
    
    Signed-off-by: Slava Koptilin <[email protected]>
---
 .../ignite/cli/commands/sql/ItSqlCommandTest.java  | 56 ++++++++++++++--
 .../exception/handler/SqlExceptionHandler.java     | 77 +++++++++++++++++++++-
 .../ignite/cli/core/style/AnsiStringSupport.java   | 16 ++---
 .../cli/core/style/component/CommonMessages.java   |  4 +-
 .../cli/core/style/element/MarkedUiElement.java    |  4 +-
 .../ignite/cli/core/style/element/UiElement.java   |  4 +-
 .../ignite/cli/core/style/element/UiElements.java  |  4 +-
 .../ignite/cli/core/style/element/UiString.java    |  4 +-
 .../client/handler/JdbcQueryEventHandlerImpl.java  |  4 +-
 .../apache/ignite/internal/jdbc/JdbcStatement.java | 13 +---
 .../java/org/apache/ignite/lang/ErrorGroup.java    |  4 +-
 .../org/apache/ignite/lang/ErrorGroupTest.java     | 31 +++++++++
 .../ignite/internal/sql/engine/util/Commons.java   |  8 ++-
 13 files changed, 180 insertions(+), 49 deletions(-)

diff --git 
a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/sql/ItSqlCommandTest.java
 
b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/sql/ItSqlCommandTest.java
index 034a4d2b5f..ecf746b239 100644
--- 
a/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/sql/ItSqlCommandTest.java
+++ 
b/modules/cli/src/integrationTest/java/org/apache/ignite/cli/commands/sql/ItSqlCommandTest.java
@@ -31,7 +31,6 @@ import org.junit.jupiter.api.TestInfo;
  * Tests for {@link SqlCommand}.
  */
 class ItSqlCommandTest extends CliCommandTestInitializedIntegrationBase {
-
     @BeforeEach
     @Override
     public void setUp(TestInfo testInfo) throws Exception {
@@ -64,8 +63,7 @@ class ItSqlCommandTest extends 
CliCommandTestInitializedIntegrationBase {
         assertAll(
                 () -> assertExitCodeIs(1),
                 this::assertOutputIsEmpty,
-                // TODO: https://issues.apache.org/jira/browse/IGNITE-17090
-                () -> assertErrOutputIs(CLIENT_CONNECTION_FAILED_MESSAGE + 
System.lineSeparator())
+                () -> assertErrOutputContains(CLIENT_CONNECTION_FAILED_MESSAGE)
         );
     }
 
@@ -77,9 +75,55 @@ class ItSqlCommandTest extends 
CliCommandTestInitializedIntegrationBase {
         assertAll(
                 () -> assertExitCodeIs(1),
                 this::assertOutputIsEmpty,
-                // TODO: https://issues.apache.org/jira/browse/IGNITE-17090
-                () -> assertErrOutputIs("SQL query parsing error" + 
System.lineSeparator()
-                        + "Sql query execution failed." + 
System.lineSeparator())
+                () -> assertErrOutputContains("Failed to parse query: 
Encountered \"\" at line 1, column 6")
+        );
+    }
+
+    @Test
+    @DisplayName("Should display readable error when wrong engine is given on 
CREATE TABLE")
+    void incorrectEngineOnCreate() {
+        execute("sql", "create table mytable1(i int, j int, primary key (i)) 
with engine='nusuch'", "--jdbc-url", JDBC_URL);
+
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("Unexpected table option 
[option=ENGINE")
+        );
+    }
+
+    @Test
+    @DisplayName("Should display readable error when not SQL expression given")
+    void notSqlExpression() {
+        execute("sql", "asdf", "--jdbc-url", JDBC_URL);
+
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("Failed to parse query: 
Non-query expression encountered in illegal context")
+        );
+    }
+
+    @Test
+    @DisplayName("Should display readable error when select from non existent 
table")
+    void noSuchTableSelect() {
+        execute("sql", "select * from nosuchtable", "--jdbc-url", JDBC_URL);
+
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("From line 1, column 15 to line 
1, column 25: Object 'NOSUCHTABLE' not found")
+        );
+    }
+
+    @Test
+    @DisplayName("Should display readable error when create table without PK")
+    void createTableWithoutPk() {
+        execute("sql", "create table mytable(i int)", "--jdbc-url", JDBC_URL);
+
+        assertAll(
+                () -> assertExitCodeIs(1),
+                this::assertOutputIsEmpty,
+                () -> assertErrOutputContains("Table without PRIMARY KEY is 
not supported")
         );
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/SqlExceptionHandler.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/SqlExceptionHandler.java
index d3d62e87b7..7d498b8aac 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/SqlExceptionHandler.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/exception/handler/SqlExceptionHandler.java
@@ -18,12 +18,24 @@
 package org.apache.ignite.cli.core.exception.handler;
 
 import java.sql.SQLException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+import java.util.function.Function;
 import org.apache.ignite.cli.core.exception.ExceptionHandler;
 import org.apache.ignite.cli.core.exception.ExceptionWriter;
 import org.apache.ignite.cli.core.style.component.ErrorUiComponent;
+import 
org.apache.ignite.cli.core.style.component.ErrorUiComponent.ErrorComponentBuilder;
+import org.apache.ignite.client.IgniteClientConnectionException;
 import org.apache.ignite.internal.jdbc.proto.SqlStateCode;
 import org.apache.ignite.internal.logger.IgniteLogger;
 import org.apache.ignite.internal.logger.Loggers;
+import org.apache.ignite.internal.util.ExceptionUtils;
+import org.apache.ignite.lang.ErrorGroup;
+import org.apache.ignite.lang.ErrorGroups.Client;
+import org.apache.ignite.lang.ErrorGroups.Sql;
+import org.apache.ignite.lang.IgniteCheckedException;
+import org.apache.ignite.lang.IgniteException;
 
 /**
  * Exception handler for {@link SQLException}.
@@ -38,9 +50,52 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
     public static final String CLIENT_CONNECTION_FAILED_MESSAGE = "Connection 
failed";
 
     public static final String CONNECTION_BROKE_MESSAGE = "Connection error";
+    public static final String UNRECOGNIZED_ERROR_MESSAGE = "Unrecognized 
error while processing SQL query ";
+
+    private final Map<Integer, Function<IgniteException, 
ErrorComponentBuilder>> sqlExceptionMappers = new HashMap<>();
+
+    /** Default constructor. */
+    public SqlExceptionHandler() {
+        sqlExceptionMappers.put(Client.CONNECTION_ERR, 
this::connectionErrUiComponent);
+        sqlExceptionMappers.put(Sql.QUERY_INVALID_ERR, 
this::invalidQueryErrUiComponent);
+    }
+
+    private ErrorComponentBuilder invalidQueryErrUiComponent(IgniteException 
e) {
+        return fromExWithHeader(PARSING_ERROR_MESSAGE, e.errorCode(), 
e.traceId(), e.getMessage());
+    }
+
+    private ErrorComponentBuilder unrecognizedErrComponent(IgniteException e) {
+        return fromExWithHeader(UNRECOGNIZED_ERROR_MESSAGE, e.errorCode(), 
e.traceId(), e.getMessage());
+    }
+
+    private ErrorComponentBuilder connectionErrUiComponent(IgniteException e) {
+        if (e.getCause() instanceof IgniteClientConnectionException) {
+            IgniteClientConnectionException cause = 
(IgniteClientConnectionException) e.getCause();
+            return fromExWithHeader(CLIENT_CONNECTION_FAILED_MESSAGE, 
cause.errorCode(), cause.traceId(), cause.getMessage());
+        }
+
+        return fromExWithHeader(CLIENT_CONNECTION_FAILED_MESSAGE, 
e.errorCode(), e.traceId(), e.getMessage());
+    }
+
+    private static ErrorComponentBuilder fromExWithHeader(String header, int 
errorCode, UUID traceId, String message) {
+        return ErrorUiComponent.builder()
+                .header(header)
+                .errorCode(String.valueOf(errorCode))
+                .traceId(traceId)
+                .details(ErrorGroup.extractCauseMessage(message));
+    }
 
     @Override
     public int handle(ExceptionWriter err, SQLException e) {
+        Throwable unwrappedCause = ExceptionUtils.unwrapCause(e.getCause());
+        if (unwrappedCause instanceof IgniteException) {
+            return handleIgniteException(err, (IgniteException) 
unwrappedCause);
+        }
+
+        if (unwrappedCause instanceof IgniteCheckedException) {
+            return handleIgniteCheckedException(err, (IgniteCheckedException) 
unwrappedCause);
+        }
+
         var errorComponentBuilder = ErrorUiComponent.builder();
 
         switch (e.getSQLState()) {
@@ -50,7 +105,7 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
                 errorComponentBuilder.header(CONNECTION_BROKE_MESSAGE);
                 break;
             case SqlStateCode.PARSING_EXCEPTION:
-                
errorComponentBuilder.header(PARSING_ERROR_MESSAGE).details(e.getMessage());
+                
errorComponentBuilder.header(PARSING_ERROR_MESSAGE).details(ErrorGroup.extractCauseMessage(e.getMessage()));
                 break;
             case SqlStateCode.INVALID_PARAMETER_VALUE:
                 errorComponentBuilder.header(INVALID_PARAMETER_MESSAGE);
@@ -60,13 +115,31 @@ public class SqlExceptionHandler implements 
ExceptionHandler<SQLException> {
                 break;
             default:
                 LOG.error("Unrecognized error", e);
-                errorComponentBuilder.header("Unrecognized error while process 
SQL query");
+                errorComponentBuilder.header("SQL query execution 
error").details(e.getMessage());
         }
 
         err.write(errorComponentBuilder.build().render());
         return 1;
     }
 
+    /** 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(), 
this::unrecognizedErrComponent);
+
+        String renderedError = errorComponentBuilder.apply(e).build().render();
+        err.write(renderedError);
+
+        return 1;
+    }
+
+    private int handleIgniteCheckedException(ExceptionWriter err, 
IgniteCheckedException e) {
+        String renderedError = fromExWithHeader(UNRECOGNIZED_ERROR_MESSAGE, 
e.errorCode(), e.traceId(), e.getMessage())
+                .build().render();
+        err.write(renderedError);
+
+        return 1;
+    }
+
     @Override
     public Class<SQLException> applicableException() {
         return SQLException.class;
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/AnsiStringSupport.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/AnsiStringSupport.java
index e9e20a6e62..d69f7e07d5 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/AnsiStringSupport.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/AnsiStringSupport.java
@@ -33,9 +33,7 @@ public final class AnsiStringSupport {
         return new Fg(color);
     }
 
-    /**
-     * Can mark the string as a ANSI string.
-     */
+    /** Can mark the string as a ANSI string. */
     public interface Marker {
         String mark(String content);
     }
@@ -45,6 +43,7 @@ public final class AnsiStringSupport {
      */
     public static class Fg implements Marker {
         private final Color color;
+
         private Style style;
 
         private Fg(Color color) {
@@ -56,9 +55,7 @@ public final class AnsiStringSupport {
             return this;
         }
 
-        /**
-         * Marks given text with the configured before style.
-         */
+        /** Marks given text with the configured before style. */
         public String mark(String textToMark) {
             if (style == Style.BOLD) {
                 return String.format("@|fg(%d),bold %s|@", color.code, 
textToMark);
@@ -67,12 +64,9 @@ public final class AnsiStringSupport {
         }
     }
 
-    /**
-     * Represents the text style.
-     */
+    /** Represents the text style. */
     public enum Style implements Marker {
-        BOLD("bold"),
-        UNDERLINE("underline");
+        BOLD("bold"), UNDERLINE("underline");
 
         private final String value;
 
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/component/CommonMessages.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/component/CommonMessages.java
index 7bbf3f3518..dae4fe5bfb 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/component/CommonMessages.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/component/CommonMessages.java
@@ -19,9 +19,7 @@ package org.apache.ignite.cli.core.style.component;
 
 import org.apache.ignite.cli.core.style.element.UiElements;
 
-/**
- * Common UI messages.
- */
+/** Common UI messages. */
 public class CommonMessages {
     public static MessageUiComponent CONNECT_OR_USE_CLUSTER_URL_MESSAGE = 
MessageUiComponent.builder()
             .message("You are not connected to node")
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/MarkedUiElement.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/MarkedUiElement.java
index 56522c1f3b..24c50dc9dc 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/MarkedUiElement.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/MarkedUiElement.java
@@ -19,9 +19,7 @@ package org.apache.ignite.cli.core.style.element;
 
 import org.apache.ignite.cli.core.style.AnsiStringSupport.Marker;
 
-/**
- * IU element that is marked with provided ANSI marker.
- */
+/** IU element that is marked with provided ANSI marker. */
 public class MarkedUiElement implements UiElement {
     private final String content;
 
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElement.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElement.java
index a808770e69..941d5bd2a9 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElement.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElement.java
@@ -17,9 +17,7 @@
 
 package org.apache.ignite.cli.core.style.element;
 
-/**
- * Can represent UI Element as an ANSI string.
- */
+/** Can represent UI Element as an ANSI string. */
 public interface UiElement {
     /** Represents the UI Element as ansi String. For example '@|fg(1) text 
|@'. */
     String represent();
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElements.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElements.java
index 224130bb7a..240c1314d9 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElements.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiElements.java
@@ -22,9 +22,7 @@ import static 
org.apache.ignite.cli.core.style.AnsiStringSupport.fg;
 import org.apache.ignite.cli.core.style.AnsiStringSupport.Color;
 import org.apache.ignite.cli.core.style.AnsiStringSupport.Style;
 
-/**
- * Defines all UI Elements that are used in the CLI.
- */
+/** Defines all UI Elements that are used in the CLI. */
 public class UiElements {
     public static UiElement url(String content) {
         return new MarkedUiElement(content, Style.UNDERLINE);
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiString.java
 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiString.java
index ee92072444..c7aed9f84a 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiString.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/cli/core/style/element/UiString.java
@@ -19,9 +19,7 @@ package org.apache.ignite.cli.core.style.element;
 
 import java.util.Arrays;
 
-/**
- * Can format the string with UI Elements.
- */
+/** Can format the string with UI Elements. */
 public class UiString {
     /** Accepts the String template with UI Elements. */
     public static String format(String template, UiElement... elements) {
diff --git 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/JdbcQueryEventHandlerImpl.java
 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/JdbcQueryEventHandlerImpl.java
index 53596c2a60..79f67525a8 100644
--- 
a/modules/client-handler/src/main/java/org/apache/ignite/client/handler/JdbcQueryEventHandlerImpl.java
+++ 
b/modules/client-handler/src/main/java/org/apache/ignite/client/handler/JdbcQueryEventHandlerImpl.java
@@ -57,6 +57,7 @@ import org.apache.ignite.internal.sql.engine.QueryValidator;
 import org.apache.ignite.internal.sql.engine.exec.QueryValidationException;
 import org.apache.ignite.internal.sql.engine.prepare.QueryPlan;
 import org.apache.ignite.internal.sql.engine.prepare.QueryPlan.Type;
+import org.apache.ignite.internal.util.ExceptionUtils;
 import org.apache.ignite.lang.IgniteInternalCheckedException;
 import org.apache.ignite.lang.IgniteInternalException;
 import org.apache.ignite.sql.ResultSetMetadata;
@@ -272,10 +273,11 @@ public class JdbcQueryEventHandlerImpl implements 
JdbcQueryEventHandler {
      * @return StringWriter filled with exception.
      */
     private StringWriter getWriterWithStackTrace(Throwable t) {
+        String message = ExceptionUtils.unwrapCause(t).getMessage();
         StringWriter sw = new StringWriter();
         PrintWriter pw = new PrintWriter(sw);
 
-        t.printStackTrace(pw);
+        pw.print(message);
         return sw;
     }
 
diff --git 
a/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcStatement.java
 
b/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcStatement.java
index 3ad1a8b8f8..b9c1906880 100644
--- 
a/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcStatement.java
+++ 
b/modules/client/src/main/java/org/apache/ignite/internal/jdbc/JdbcStatement.java
@@ -46,7 +46,6 @@ import 
org.apache.ignite.internal.jdbc.proto.event.JdbcQuerySingleResult;
 import org.apache.ignite.internal.jdbc.proto.event.Response;
 import org.apache.ignite.internal.util.ArrayUtils;
 import org.apache.ignite.internal.util.CollectionUtils;
-import org.apache.ignite.lang.IgniteException;
 
 /**
  * Jdbc statement implementation.
@@ -734,16 +733,6 @@ public class JdbcStatement implements Statement {
     }
 
     private static SQLException toSqlException(CompletionException e) {
-        if (e.getCause() instanceof IgniteException) {
-            IgniteException cause = (IgniteException) e.getCause();
-            String message = cause.getMessage();
-
-            if (message != null) {
-                if (message.contains("Failed to parse query")) {
-                    return new SQLException("Sql query execution failed.", 
SqlStateCode.PARSING_EXCEPTION, e);
-                }
-            }
-        }
-        return new SQLException("Internal server error.", 
SqlStateCode.INTERNAL_ERROR, e);
+        return new SQLException(e);
     }
 }
diff --git a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroup.java 
b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroup.java
index 3f18678b13..88c6b2d7a1 100755
--- a/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroup.java
+++ b/modules/core/src/main/java/org/apache/ignite/lang/ErrorGroup.java
@@ -17,6 +17,8 @@
 
 package org.apache.ignite.lang;
 
+import static java.util.regex.Pattern.DOTALL;
+
 import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
 import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
 import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
@@ -36,7 +38,7 @@ public class ErrorGroup {
 
     /** Error message pattern. */
     private static final Pattern EXCEPTION_MESSAGE_PATTERN =
-            
Pattern.compile("(.*)(IGN)-([A-Z]+)-(\\d+)\\s(TraceId:)([a-f0-9]{8}(?:-[a-f0-9]{4}){4}[a-f0-9]{8})(\\s?)(.*)");
+            
Pattern.compile("(.*)(IGN)-([A-Z]+)-(\\d+)\\s(TraceId:)([a-f0-9]{8}(?:-[a-f0-9]{4}){4}[a-f0-9]{8})(\\s?)(.*)",
 DOTALL);
 
     /** List of all registered error groups. */
     private static final Int2ObjectMap<ErrorGroup> registeredGroups = new 
Int2ObjectOpenHashMap<>();
diff --git 
a/modules/core/src/test/java/org/apache/ignite/lang/ErrorGroupTest.java 
b/modules/core/src/test/java/org/apache/ignite/lang/ErrorGroupTest.java
index 65e95429f5..3063d33398 100644
--- a/modules/core/src/test/java/org/apache/ignite/lang/ErrorGroupTest.java
+++ b/modules/core/src/test/java/org/apache/ignite/lang/ErrorGroupTest.java
@@ -20,6 +20,8 @@ package org.apache.ignite.lang;
 import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.equalTo;
 
+import java.util.UUID;
+import org.apache.ignite.lang.ErrorGroups.Common;
 import org.junit.jupiter.api.Test;
 
 class ErrorGroupTest {
@@ -46,4 +48,33 @@ class ErrorGroupTest {
         // Then
         assertThat(extractedMessage, equalTo(""));
     }
+
+    @Test
+    void createsErrorMassage() {
+        // Given
+        UUID traceId = UUID.fromString("24103638-d079-4a19-a8f6-ca9c23662908");
+        int code = Common.UNEXPECTED_ERR;
+        String reason = "I'm the reason";
+
+        // When
+        String errorMessage = ErrorGroup.errorMessage(traceId, code, reason);
+
+        // Then
+        assertThat(errorMessage, equalTo("IGN-CMN-1 
TraceId:24103638-d079-4a19-a8f6-ca9c23662908 I'm the reason"));
+    }
+
+    @Test
+    void doesNotDuplicateErrorCodeAndTraceId() {
+        // Given
+        UUID traceId = UUID.fromString("24103638-d079-4a19-a8f6-ca9c23662908");
+        int code = Common.UNEXPECTED_ERR;
+        IgniteInternalException cause = new IgniteInternalException(traceId, 
code, "I'm the\n reason\n");
+        IgniteInternalException origin = new IgniteInternalException(traceId, 
code, cause);
+
+        // When
+        String errorMessage = origin.getMessage();
+
+        // Then error code and traceId are not duplicated
+        assertThat(errorMessage, equalTo("IGN-CMN-1 
TraceId:24103638-d079-4a19-a8f6-ca9c23662908 I'm the\n reason\n"));
+    }
 }
diff --git 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
index 0ae238066d..ebaebbc4cf 100644
--- 
a/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
+++ 
b/modules/sql-engine/src/main/java/org/apache/ignite/internal/sql/engine/util/Commons.java
@@ -19,6 +19,8 @@ package org.apache.ignite.internal.sql.engine.util;
 
 import static 
org.apache.ignite.internal.sql.engine.util.BaseQueryContext.CLUSTER;
 import static org.apache.ignite.internal.util.CollectionUtils.nullOrEmpty;
+import static org.apache.ignite.internal.util.ExceptionUtils.withCauseAndCode;
+import static org.apache.ignite.lang.ErrorGroup.extractCauseMessage;
 import static org.apache.ignite.lang.ErrorGroups.Sql.QUERY_INVALID_ERR;
 
 import it.unimi.dsi.fastutil.ints.IntArrayList;
@@ -815,7 +817,11 @@ public final class Commons {
         try {
             return parse(new SourceStringReader(qry), parserCfg);
         } catch (SqlParseException e) {
-            throw new SqlException(QUERY_INVALID_ERR, "Failed to parse query", 
e);
+            throw withCauseAndCode(
+                    SqlException::new,
+                    QUERY_INVALID_ERR,
+                    "Failed to parse query: " + 
extractCauseMessage(e.getMessage()),
+                    e);
         }
     }
 

Reply via email to