diff --git a/CHANGELOG.md b/CHANGELOG.md index 098f1a172..7f65a79e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,6 +137,9 @@ ### Bug Fixes +- **[jdbc-v2]** Fixed `SQLException#getSQLState()` returning the generic data-exception state `22000` + when ClickHouse reports an unknown table. The driver now returns `42S02` (base table or view not found) while + preserving the ClickHouse error code and original exception. (https://github.com/ClickHouse/clickhouse-java/issues/3104) - **[client-v2]** Fixed truncated LZ4 stream errors reporting literal `{0}` and `{1}` placeholders instead of the number of bytes read and expected. (https://github.com/ClickHouse/clickhouse-java/issues/3108) - **[jdbc-v2]** Fixed `DatabaseMetaData#getTables` reporting `TABLE_TYPE = TABLE` for a table with the `BigQuery` diff --git a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ExceptionUtils.java b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ExceptionUtils.java index d0947d735..81ebb4243 100644 --- a/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ExceptionUtils.java +++ b/jdbc-v2/src/main/java/com/clickhouse/jdbc/internal/ExceptionUtils.java @@ -21,6 +21,7 @@ public final class ExceptionUtils { public static final String SQL_STATE_INVALID_SCHEMA = "3F000"; public static final String SQL_STATE_INVALID_TX_STATE = "25000"; public static final String SQL_STATE_DATA_EXCEPTION = "22000"; + private static final String SQL_STATE_TABLE_NOT_FOUND = "42S02"; // Used only when feature is not supported public static final String SQL_STATE_FEATURE_NOT_SUPPORTED = "0A000"; // Used only when method is called on wrong object type (for example, PreparedStatement.addBatch(String)) @@ -60,7 +61,11 @@ public static SQLException toSqlState(String message, String debugMessage, Excep } else if (cause instanceof ConnectionInitiationException) { return new SQLException(exceptionMessage, SQL_STATE_CONNECTION_EXCEPTION, cause); } else if (cause instanceof ServerException) { - return new SQLException(exceptionMessage, SQL_STATE_DATA_EXCEPTION, ((ServerException) cause).getCode(), cause); + int errorCode = ((ServerException) cause).getCode(); + String sqlState = errorCode == ServerException.TABLE_NOT_FOUND + ? SQL_STATE_TABLE_NOT_FOUND + : SQL_STATE_DATA_EXCEPTION; + return new SQLException(exceptionMessage, sqlState, errorCode, cause); } else if (cause instanceof ClientException) { return new SQLException(exceptionMessage, SQL_STATE_CLIENT_ERROR, cause); } else if (cause instanceof MalformedURLException) { diff --git a/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/ExceptionUtilsTest.java b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/ExceptionUtilsTest.java new file mode 100644 index 000000000..0fc3802cb --- /dev/null +++ b/jdbc-v2/src/test/java/com/clickhouse/jdbc/internal/ExceptionUtilsTest.java @@ -0,0 +1,31 @@ +package com.clickhouse.jdbc.internal; + +import com.clickhouse.client.api.ServerException; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.sql.SQLException; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertSame; + +public class ExceptionUtilsTest { + @DataProvider + public Object[][] serverExceptions() { + return new Object[][] { + {ServerException.TABLE_NOT_FOUND, "42S02"}, + {ServerException.ErrorCodes.UNKNOWN_SETTING.getCode(), ExceptionUtils.SQL_STATE_DATA_EXCEPTION} + }; + } + + @Test(dataProvider = "serverExceptions") + public void shouldMapServerExceptionToSqlState(int errorCode, String expectedSqlState) { + ServerException cause = new ServerException(errorCode, "Server error", 400, "query-id"); + + SQLException exception = ExceptionUtils.toSqlState(cause); + + assertEquals(exception.getSQLState(), expectedSqlState); + assertEquals(exception.getErrorCode(), errorCode); + assertSame(exception.getCause(), cause); + } +}