From 5c0874281e1daecf72dbe7f3eb62221515e5d566 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Mon, 28 Aug 2017 20:18:29 +0300 Subject: [PATCH 01/43] IGNITE-5620 Began sorting out errors. --- .../processors/query/IgniteSQLException.java | 78 +++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index 0666493f41731..3040e88b4d9ad 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -22,6 +22,27 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.jetbrains.annotations.Nullable; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CACHE_NOT_FOUND; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_ALREADY_EXISTS; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_NOT_FOUND; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CONCURRENT_UPDATE; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.DUPLICATE_KEY; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.ENTRY_PROCESSING; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_ALREADY_EXISTS; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_NOT_FOUND; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.KEY_UPDATE; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_KEY; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_VALUE; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.PARSING; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.STMT_TYPE_MISMATCH; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_ALREADY_EXISTS; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_DROP_FAILED; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_NOT_FOUND; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_ELEMENT_TYPE; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_OPERATION; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNSUPPORTED_OPERATION; + /** * Specific exception bearing information about query processing errors for more detailed * errors in JDBC driver. @@ -93,4 +114,61 @@ public int statusCode() { public SQLException toJdbcException() { return new SQLException(getMessage(), sqlState, statusCode, this); } + + /** + * + * @param statusCode + * @return + * @see Wikipedia: SQLSTATE spec. + */ + private static String codeToSqlState(int statusCode) { + switch (statusCode) { + case DUPLICATE_KEY: + return "23000"; // Generic value for "integrity constraint violation" 23 class. + + case NULL_KEY: + case NULL_VALUE: + return "22004"; // "Null value not allowed". + + case UNSUPPORTED_OPERATION: + return "0A000"; // Generic value for "feature not supported" 0A class. + + case CONCURRENT_UPDATE: + return "40000"; // Generic value for "tx rollback" 0A class. + + case PARSING: + return "42000"; // Generic value for "syntax error or access rule violation" 42 class. + + // 42 - class for "syntax error or access rule violation" + error specific part. + case TABLE_NOT_FOUND: + case INDEX_ALREADY_EXISTS: + case STMT_TYPE_MISMATCH: + case INDEX_NOT_FOUND: + case TABLE_ALREADY_EXISTS: + case COLUMN_NOT_FOUND: + case COLUMN_ALREADY_EXISTS: + return "42" + String.valueOf(statusCode).substring(1); + + case UNEXPECTED_OPERATION: + case UNEXPECTED_ELEMENT_TYPE: + case KEY_UPDATE: + return "421" + String.valueOf(statusCode).substring(2); + + // Internal errors - XX class. + case ENTRY_PROCESSING: + return "XX001"; + + case TABLE_DROP_FAILED: + return "XX002"; + + case NULL_TABLE_DESCRIPTOR: + return "XX003"; + + case CACHE_NOT_FOUND: + return "XX004"; + + default: + return "50000"; // Generic value for custom "50" class. + } + } } From 71c3bb261ad9c80948fc797865dfe3583cee372e Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Tue, 29 Aug 2017 18:57:34 +0300 Subject: [PATCH 02/43] IGNITE-5620 contd --- .../processors/query/IgniteSQLException.java | 56 +++++++++++-------- 1 file changed, 33 insertions(+), 23 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index 3040e88b4d9ad..21090184d3a3e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -41,6 +41,7 @@ import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_NOT_FOUND; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_ELEMENT_TYPE; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_OPERATION; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNKNOWN; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNSUPPORTED_OPERATION; /** @@ -61,7 +62,7 @@ public class IgniteSQLException extends IgniteException { /** */ public IgniteSQLException(String msg) { - this(msg, null, 0); + this(msg, UNKNOWN, null); } /** @@ -69,35 +70,27 @@ public IgniteSQLException(String msg) { */ public IgniteSQLException(SQLException cause) { super(cause); - this.sqlState = null; - this.statusCode = 0; + this.sqlState = cause.getSQLState(); + this.statusCode = UNKNOWN; } /** */ public IgniteSQLException(String msg, @Nullable Throwable cause) { - super(msg, cause); - this.sqlState = null; - this.statusCode = 0; + this(msg, UNKNOWN, cause); } /** */ public IgniteSQLException(String msg, int statusCode, @Nullable Throwable cause) { super(msg, cause); - this.sqlState = null; - this.statusCode = statusCode; - } - - /** */ - public IgniteSQLException(String msg, String sqlState, int statusCode) { - super(msg); - this.sqlState = sqlState; + this.sqlState = (cause instanceof SQLException ? ((SQLException) cause).getSQLState() : + codeToSqlState(statusCode)); this.statusCode = statusCode; } /** */ public IgniteSQLException(String msg, int statusCode) { super(msg); - this.sqlState = null; + this.sqlState = codeToSqlState(statusCode); this.statusCode = statusCode; } @@ -116,10 +109,11 @@ public SQLException toJdbcException() { } /** - * - * @param statusCode - * @return + * Map Ignite specific error code to standard SQL state. + * @param statusCode Ignite specific error code. + * @return SQL state string. * @see Wikipedia: SQLSTATE spec. + * @see IgniteQueryErrorCode */ private static String codeToSqlState(int statusCode) { switch (statusCode) { @@ -141,20 +135,36 @@ private static String codeToSqlState(int statusCode) { // 42 - class for "syntax error or access rule violation" + error specific part. case TABLE_NOT_FOUND: + return "42001"; + + case TABLE_ALREADY_EXISTS: + return "42002"; + case INDEX_ALREADY_EXISTS: - case STMT_TYPE_MISMATCH: + return "42003"; + case INDEX_NOT_FOUND: - case TABLE_ALREADY_EXISTS: + return "42004"; + case COLUMN_NOT_FOUND: + return "42005"; + case COLUMN_ALREADY_EXISTS: - return "42" + String.valueOf(statusCode).substring(1); + return "42006"; + + case STMT_TYPE_MISMATCH: + return "42007"; case UNEXPECTED_OPERATION: + return "42008"; + case UNEXPECTED_ELEMENT_TYPE: + return "42009"; + case KEY_UPDATE: - return "421" + String.valueOf(statusCode).substring(2); + return "42010"; - // Internal errors - XX class. + // Internal errors - custom "XX" class. case ENTRY_PROCESSING: return "XX001"; From 5a909c68e31e6280fde5b0fa7bd9e01aa4b6b0f8 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Tue, 29 Aug 2017 22:07:04 +0300 Subject: [PATCH 03/43] IGNITE-5620 JDBC error tests - started --- .../internal/jdbc2/JdbcErrorsSelfTest.java | 33 +++++++ .../jdbc/JdbcErrorsAbstractSelfTest.java | 86 +++++++++++++++++++ .../jdbc/thin/JdbcThinErrorsSelfTest.java | 33 +++++++ .../ignite/internal/jdbc2/JdbcStatement.java | 7 ++ .../processors/query/IgniteSQLException.java | 19 +--- 5 files changed, 160 insertions(+), 18 deletions(-) create mode 100644 modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java create mode 100644 modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java create mode 100644 modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java new file mode 100644 index 0000000000000..eadfb10dc70cc --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc2; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; + +/** + * Created by apaschenko on 29.08.17. + */ +public class JdbcErrorsSelfTest extends JdbcErrorsAbstractSelfTest { + /** {@inheritDoc} */ + @Override protected Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:ignite:cfg://cache=test@" + CFG_PATH); + } +} diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java new file mode 100644 index 0000000000000..19ae018dfffb1 --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -0,0 +1,86 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.jdbc; + +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.util.Collections; +import org.apache.ignite.cache.QueryEntity; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.lang.IgniteCallable; +import org.apache.ignite.testframework.GridTestUtils; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; + +/** + * Created by apaschenko on 29.08.17. + */ +public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest { + protected static final String CFG_PATH = "modules/clients/src/test/config/jdbc-config.xml"; + + /** {@inheritDoc} */ + @Override protected void beforeTestsStarted() throws Exception { + super.beforeTestsStarted(); + + startGrid(getConfiguration(getTestIgniteInstanceName(0)) + .setCacheConfiguration(new CacheConfiguration("test") + .setQueryEntities(Collections.singletonList(new QueryEntity(Integer.class, Integer.class))))); + + //startGrid(loadConfiguration(CFG_PATH).setIgniteInstanceName(getTestIgniteInstanceName(0))); + } + + /** {@inheritDoc} */ + @Override protected void afterTestsStopped() throws Exception { + stopAllGrids(); + + super.afterTestsStopped(); + } + + public void testTableErrors() { + + } + + public void testIndexErrors() { + + } + + public void testDmlErrors() throws SQLException { + checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, null)", "22004"); + } + + protected abstract Connection getConnection() throws SQLException; + + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + protected void checkErrorState(String sql, String expState) throws SQLException { + try (Connection conn = getConnection()) { + try (final PreparedStatement stmt = conn.prepareStatement(sql)) { + SQLException ex = (SQLException)GridTestUtils.assertThrows(null, new IgniteCallable() { + @Override public Void call() throws Exception { + stmt.execute(); + + fail(); + + return null; + } + }, SQLException.class, null); + + assertEquals(expState, ex.getSQLState()); + } + } + } +} diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java new file mode 100644 index 0000000000000..16a05eb7fac69 --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java @@ -0,0 +1,33 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.jdbc.thin; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; + +/** + * Created by apaschenko on 29.08.17. + */ +public class JdbcThinErrorsSelfTest extends JdbcErrorsAbstractSelfTest { + /** {@inheritDoc} */ + @Override protected Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1"); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java index 4e05db4ee3f4d..984aadfa6fb51 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java @@ -31,6 +31,7 @@ import java.util.Map; import java.util.Set; import java.util.UUID; +import javax.cache.CacheException; import org.apache.ignite.Ignite; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; @@ -361,6 +362,12 @@ sql, null, loc, getArgs(), fetchSize, uuid, conn.isLocalQuery(), conn.isCollocat catch (IgniteSQLException e) { throw e.toJdbcException(); } + catch (CacheException e) { + if (e.getCause() instanceof IgniteSQLException) + throw ((IgniteSQLException) e.getCause()).toJdbcException(); + else + throw new SQLException("Failed to query Ignite.", e); + } catch (Exception e) { throw new SQLException("Failed to query Ignite.", e); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index 21090184d3a3e..fa95ccf106e75 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -22,22 +22,18 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.jetbrains.annotations.Nullable; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CACHE_NOT_FOUND; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_ALREADY_EXISTS; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_NOT_FOUND; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CONCURRENT_UPDATE; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.DUPLICATE_KEY; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.ENTRY_PROCESSING; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_ALREADY_EXISTS; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_NOT_FOUND; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.KEY_UPDATE; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_KEY; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_TABLE_DESCRIPTOR; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_VALUE; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.PARSING; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.STMT_TYPE_MISMATCH; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_ALREADY_EXISTS; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_DROP_FAILED; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_NOT_FOUND; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_ELEMENT_TYPE; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_OPERATION; @@ -128,7 +124,7 @@ private static String codeToSqlState(int statusCode) { return "0A000"; // Generic value for "feature not supported" 0A class. case CONCURRENT_UPDATE: - return "40000"; // Generic value for "tx rollback" 0A class. + return "40000"; // Generic value for "tx rollback" 40 class. case PARSING: return "42000"; // Generic value for "syntax error or access rule violation" 42 class. @@ -164,19 +160,6 @@ private static String codeToSqlState(int statusCode) { case KEY_UPDATE: return "42010"; - // Internal errors - custom "XX" class. - case ENTRY_PROCESSING: - return "XX001"; - - case TABLE_DROP_FAILED: - return "XX002"; - - case NULL_TABLE_DESCRIPTOR: - return "XX003"; - - case CACHE_NOT_FOUND: - return "XX004"; - default: return "50000"; // Generic value for custom "50" class. } From d907d785814b73f353d736895d063158ff1bb578 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Wed, 30 Aug 2017 19:47:11 +0300 Subject: [PATCH 04/43] Thin JDBC - errors --- .../jdbc/JdbcErrorsAbstractSelfTest.java | 2 - .../odbc/SqlListenerNioListener.java | 10 ++- .../processors/odbc/jdbc/JdbcErrorResult.java | 88 +++++++++++++++++++ .../odbc/jdbc/JdbcRequestHandler.java | 48 +++++++--- .../processors/odbc/jdbc/JdbcResponse.java | 14 ++- .../processors/odbc/jdbc/JdbcResult.java | 8 ++ .../processors/query/IgniteSQLException.java | 2 +- 7 files changed, 150 insertions(+), 22 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java index 19ae018dfffb1..baceda374fcfa 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -40,8 +40,6 @@ public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest startGrid(getConfiguration(getTestIgniteInstanceName(0)) .setCacheConfiguration(new CacheConfiguration("test") .setQueryEntities(Collections.singletonList(new QueryEntity(Integer.class, Integer.class))))); - - //startGrid(loadConfiguration(CFG_PATH).setIgniteInstanceName(getTestIgniteInstanceName(0))); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java index 8dad71b462ade..543b5c1f48bf4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlListenerNioListener.java @@ -51,7 +51,7 @@ public class SqlListenerNioListener extends GridNioServerListenerAdapter /** Version 2.1.0. */ private static final SqlListenerProtocolVersion VER_2_1_0 = SqlListenerProtocolVersion.create(2, 1, 0); - /** Version 2.1.5: added "lazy" flag. */ + /** Version 2.1.5: added "lazy" flag and SQL state code in response. */ private static final SqlListenerProtocolVersion VER_2_1_5 = SqlListenerProtocolVersion.create(2, 1, 5); /** Current version. */ @@ -267,12 +267,16 @@ else if (clientType == JDBC_CLIENT) { boolean autoCloseCursors = reader.readBoolean(); boolean lazyExec = false; + boolean errorResponses = false; - if (ver.compareTo(VER_2_1_5) >= 0) + if (ver.compareTo(VER_2_1_5) >= 0) { lazyExec = reader.readBoolean(); + errorResponses = true; + } + SqlListenerRequestHandler handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, - enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec); + enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec, errorResponses); SqlListenerMessageParser parser = new JdbcMessageParser(ctx); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java new file mode 100644 index 0000000000000..d224c4bd21279 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.processors.odbc.jdbc; + +import java.sql.SQLException; +import org.apache.ignite.binary.BinaryObjectException; +import org.apache.ignite.internal.binary.BinaryReaderExImpl; +import org.apache.ignite.internal.binary.BinaryWriterExImpl; + +/** + * Result carrying details needed to form proper {@link SQLException}. + */ +public class JdbcErrorResult extends JdbcResult { + /** + * Ignite specific error code. + */ + private int code; + + /** + * SQL state code. + */ + private String sqlState; + + /** + * Constructor. + */ + public JdbcErrorResult() { + super(JdbcResult.ERROR); + } + + /** + * Constructor. + * @param code Ignite specific error code. + * @param sqlState SQL state code. + */ + public JdbcErrorResult(int code, String sqlState) { + super(JdbcResult.ERROR); + this.code = code; + this.sqlState = sqlState; + } + + /** + * @return Ignite specific error code. + * @see SQLException#getErrorCode() () + */ + public int code() { + return code; + } + + /** + * @return SQL state code. + * @see SQLException#getSQLState() + */ + public String sqlState() { + return sqlState; + } + + /** {@inheritDoc} */ + @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException { + super.readBinary(reader); + + code = reader.readInt(); + sqlState = reader.readString(); + } + + /** {@inheritDoc} */ + @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException { + super.writeBinary(writer); + + writer.writeInt(code); + writer.writeString(sqlState); + } +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index d2508a660607f..97409e39b20e3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -18,6 +18,7 @@ package org.apache.ignite.internal.processors.odbc.jdbc; import java.sql.ParameterMetaData; +import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -42,6 +43,7 @@ import org.apache.ignite.internal.processors.odbc.odbc.OdbcQueryGetColumnsMetaRequest; import org.apache.ignite.internal.processors.query.GridQueryIndexDescriptor; import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.QueryUtils; import org.apache.ignite.internal.util.GridSpinBusyLock; import org.apache.ignite.internal.util.typedef.F; @@ -100,6 +102,9 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler { /** Automatic close of cursors. */ private final boolean autoCloseCursors; + /** */ + private final boolean errorResponses; + /** * Constructor. * @@ -112,10 +117,11 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler { * @param replicatedOnly Replicated only flag. * @param autoCloseCursors Flag to automatically close server cursors. * @param lazy Lazy query execution flag. + * @param errorResponses Whether detailed {@link JdbcErrorResult} objects should be sent to client on error. */ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors, boolean distributedJoins, boolean enforceJoinOrder, boolean collocated, boolean replicatedOnly, - boolean autoCloseCursors, boolean lazy) { + boolean autoCloseCursors, boolean lazy, boolean errorResponses) { this.ctx = ctx; this.busyLock = busyLock; this.maxCursors = maxCursors; @@ -125,6 +131,7 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int this.replicatedOnly = replicatedOnly; this.autoCloseCursors = autoCloseCursors; this.lazy = lazy; + this.errorResponses = errorResponses; log = ctx.log(getClass()); } @@ -186,7 +193,7 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int /** {@inheritDoc} */ @Override public SqlListenerResponse handleException(Exception e) { - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } /** {@inheritDoc} */ @@ -277,7 +284,7 @@ private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) { U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -304,7 +311,7 @@ private JdbcResponse closeQuery(JdbcQueryCloseRequest req) { U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -341,7 +348,7 @@ private JdbcResponse fetchQuery(JdbcQueryFetchRequest req) { catch (Exception e) { U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -365,7 +372,7 @@ private JdbcResponse getQueryMeta(JdbcQueryMetadataRequest req) { catch (Exception e) { U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -453,7 +460,7 @@ private JdbcResponse getTablesMeta(JdbcMetaTablesRequest req) { catch (Exception e) { U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -495,7 +502,7 @@ private JdbcResponse getColumnsMeta(JdbcMetaColumnsRequest req) { catch (Exception e) { U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -525,7 +532,7 @@ private SqlListenerResponse getIndexesMeta(JdbcMetaIndexesRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -552,7 +559,7 @@ private SqlListenerResponse getParametersMeta(JdbcMetaParamsRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -598,7 +605,7 @@ private SqlListenerResponse getPrimaryKeys(JdbcMetaPrimaryKeysRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -624,7 +631,7 @@ private SqlListenerResponse getSchemas(JdbcMetaSchemasRequest req) { catch (Exception e) { U.error(log, "Failed to get schemas metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, e.toString()); + return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); } } @@ -639,4 +646,21 @@ private static boolean matches(String str, String ptrn) { return str != null && (F.isEmpty(ptrn) || str.matches(ptrn.replace("%", ".*").replace("_", "."))); } + + private JdbcErrorResult exceptionToResult(Exception e) { + if (!errorResponses) + return null; + + SQLException sqlEx = null; + + if (e instanceof SQLException) + sqlEx = (SQLException)e; + else if (e instanceof IgniteSQLException) + sqlEx = ((IgniteSQLException)e).toJdbcException(); + + if (sqlEx != null) + return new JdbcErrorResult(sqlEx.getErrorCode(), sqlEx.getSQLState()); + else + return null; + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java index f039db769f7ab..6d7ec064f42ea 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java @@ -46,9 +46,7 @@ public JdbcResponse() { * @param res Response result. */ public JdbcResponse(JdbcResult res) { - super(STATUS_SUCCESS, null); - - this.res = res; + this(res, res instanceof JdbcErrorResult ? STATUS_FAILED : STATUS_SUCCESS, null); } /** @@ -58,11 +56,19 @@ public JdbcResponse(JdbcResult res) { * @param err Error, {@code null} if success is {@code true}. */ public JdbcResponse(int status, @Nullable String err) { - super(status, err); + this(null, status, err); assert status != STATUS_SUCCESS; } + public JdbcResponse(JdbcResult res, int status, @Nullable String err) { + super(status, err); + + assert res instanceof JdbcErrorResult ^ status == STATUS_SUCCESS; + + this.res = res; + } + /** * @return Response object. */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java index 202905bbc9e4d..2434e5958ab8b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java @@ -56,6 +56,9 @@ public class JdbcResult implements JdbcRawBinarylizable { /** Database schemas metadata result. */ static final byte META_SCHEMAS = 12; + /** Data to compose JDBC exception. */ + static final byte ERROR = 13; + /** Success status. */ private byte type; @@ -139,6 +142,11 @@ public static JdbcResult readResult(BinaryReaderExImpl reader) throws BinaryObje break; + case ERROR: + res = new JdbcErrorResult(); + + break; + default: throw new IgniteException("Unknown SQL listener request ID: [request ID=" + resId + ']'); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index fa95ccf106e75..660742965bee0 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -111,7 +111,7 @@ public SQLException toJdbcException() { * @see Wikipedia: SQLSTATE spec. * @see IgniteQueryErrorCode */ - private static String codeToSqlState(int statusCode) { + public static String codeToSqlState(int statusCode) { switch (statusCode) { case DUPLICATE_KEY: return "23000"; // Generic value for "integrity constraint violation" 23 class. From d2b1d454aad70ba8f817dc2030df443258024e5d Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Thu, 31 Aug 2017 17:33:04 +0300 Subject: [PATCH 05/43] IGNITE-5620 Errors propagation + tests. --- .../internal/jdbc2/JdbcErrorsSelfTest.java | 5 +- .../jdbc/JdbcErrorsAbstractSelfTest.java | 42 +++++++-- .../ignite/jdbc/JdbcErrorsSelfTest.java | 59 ++++++++++++ .../jdbc/thin/JdbcThinErrorsSelfTest.java | 2 +- .../internal/jdbc/thin/JdbcThinStatement.java | 4 + .../internal/jdbc/thin/JdbcThinTcpIo.java | 11 ++- .../cache/query/IgniteQueryErrorCode.java | 66 ++++++++++++- .../query/jdbc/GridCacheQueryJdbcTask.java | 20 +++- .../processors/odbc/jdbc/JdbcResponse.java | 21 ++--- .../processors/query/IgniteSQLException.java | 93 ++----------------- 10 files changed, 215 insertions(+), 108 deletions(-) create mode 100644 modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java index eadfb10dc70cc..47aa6a195e92b 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java @@ -23,9 +23,12 @@ import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; /** - * Created by apaschenko on 29.08.17. + * Test SQLSTATE codes propagation with "JDBC2" driver. */ public class JdbcErrorsSelfTest extends JdbcErrorsAbstractSelfTest { + /** Path to JDBC configuration for node that is to start. */ + private static final String CFG_PATH = "modules/clients/src/test/config/jdbc-config.xml"; + /** {@inheritDoc} */ @Override protected Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:ignite:cfg://cache=test@" + CFG_PATH); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java index baceda374fcfa..12c2923e86049 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -28,11 +28,9 @@ import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; /** - * Created by apaschenko on 29.08.17. + * Test SQLSTATE codes propagation with (any) Ignite JDBC driver. */ public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest { - protected static final String CFG_PATH = "modules/clients/src/test/config/jdbc-config.xml"; - /** {@inheritDoc} */ @Override protected void beforeTestsStarted() throws Exception { super.beforeTestsStarted(); @@ -49,22 +47,52 @@ public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest super.afterTestsStopped(); } - public void testTableErrors() { - + /** + * Test that H2 specific error codes get propagated to Ignite SQL exceptions. + * @throws SQLException if failed. + */ + public void testH2Errors() throws SQLException { + checkErrorState("gibberish", "42001"); } - public void testIndexErrors() { + /** + * Test that error codes from tables related DDL operations get propagated to Ignite SQL exceptions. + * @throws SQLException if failed. + */ + public void testTableErrors() throws SQLException { + checkErrorState("DROP TABLE \"PUBLIC\".missing", "42201"); + } + /** + * Test that error codes from indexes related DDL operations get propagated to Ignite SQL exceptions. + * @throws SQLException if failed. + */ + public void testIndexErrors() throws SQLException { + checkErrorState("DROP INDEX \"PUBLIC\".missing", "42204"); } + /** + * Test that error codes from DML operations get propagated to Ignite SQL exceptions. + * @throws SQLException if failed. + */ public void testDmlErrors() throws SQLException { checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, null)", "22004"); } + /** + * @return Connection to execute statements on. + * @throws SQLException if failed. + */ protected abstract Connection getConnection() throws SQLException; + /** + * Test that running given SQL statement yields expected SQLSTATE code. + * @param sql statement. + * @param expState expected SQLSTATE code. + * @throws SQLException if failed. + */ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - protected void checkErrorState(String sql, String expState) throws SQLException { + private void checkErrorState(String sql, String expState) throws SQLException { try (Connection conn = getConnection()) { try (final PreparedStatement stmt = conn.prepareStatement(sql)) { SQLException ex = (SQLException)GridTestUtils.assertThrows(null, new IgniteCallable() { diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java new file mode 100644 index 0000000000000..5b4c7004e52b9 --- /dev/null +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.jdbc; + +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.SQLException; +import org.apache.ignite.configuration.ConnectorConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; +import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; +import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; + +/** + * Test SQLSTATE codes propagation with "legacy" driver. + */ +public class JdbcErrorsSelfTest extends JdbcErrorsAbstractSelfTest { + /** IP finder. */ + private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); + + /** {@inheritDoc} */ + @Override protected Connection getConnection() throws SQLException { + return DriverManager.getConnection("jdbc:ignite://127.0.0.1/test"); + } + + /** {@inheritDoc} */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); + + TcpDiscoverySpi disco = new TcpDiscoverySpi(); + + disco.setIpFinder(IP_FINDER); + + cfg.setDiscoverySpi(disco); + + assert cfg.getConnectorConfiguration() == null; + + ConnectorConfiguration clientCfg = new ConnectorConfiguration(); + + cfg.setConnectorConfiguration(clientCfg); + + return cfg; + } +} diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java index 16a05eb7fac69..86cc341835f96 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java @@ -23,7 +23,7 @@ import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; /** - * Created by apaschenko on 29.08.17. + * Test SQLSTATE codes propagation with thin client driver. */ public class JdbcThinErrorsSelfTest extends JdbcErrorsAbstractSelfTest { /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 3772b83075095..967db5ca52b9e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -33,6 +33,7 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.FETCH_FORWARD; @@ -122,6 +123,9 @@ protected void execute0(String sql, List args) throws SQLException { rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), res.isQuery(), conn.io().autoCloseServerCursor(), res.updateCount()); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index b9dce0504332f..958d89c9017b4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -34,6 +34,7 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcErrorResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesRequest; @@ -57,6 +58,7 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteProductVersion; @@ -293,8 +295,15 @@ public R sendRequest(JdbcRequest req, int cap) throws IOE res.readBinary(reader); - if (res.status() != SqlListenerResponse.STATUS_SUCCESS) + if (res.status() != SqlListenerResponse.STATUS_SUCCESS) { + if (res.response() instanceof JdbcErrorResult) { + JdbcErrorResult err = (JdbcErrorResult)res.response(); + + throw new IgniteSQLException(res.error(), err.code(), err.sqlState()); + } + throw new IgniteCheckedException("Error server response: [req=" + req + ", resp=" + res + ']'); + } return (R)res.response(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index d05c9fd311484..63b56d9f3809c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -102,13 +102,75 @@ private IgniteQueryErrorCode() { } /** - * Create a {@link SQLException} for given code and message with null state. + * Create a {@link SQLException} for given code and message with detected state. * * @param msg Message. * @param code Ignite status code. * @return {@link SQLException} with given details. */ public static SQLException createJdbcSqlException(String msg, int code) { - return new SQLException(msg, null, code); + return new SQLException(msg, codeToSqlState(code), code); + } + + /** + * Map Ignite specific error code to standard SQL state. + * @param statusCode Ignite specific error code. + * @return SQL state string. + * @see Wikipedia: SQLSTATE spec. + * @see IgniteQueryErrorCode + */ + public static String codeToSqlState(int statusCode) { + switch (statusCode) { + case DUPLICATE_KEY: + return "23000"; // Generic value for "integrity constraint violation" 23 class. + + case NULL_KEY: + case NULL_VALUE: + return "22004"; // "Null value not allowed". + + case UNSUPPORTED_OPERATION: + return "0A000"; // Generic value for "feature not supported" 0A class. + + case CONCURRENT_UPDATE: + return "40000"; // Generic value for "tx rollback" 40 class. + + case PARSING: + return "42000"; // Generic value for "syntax error or access rule violation" 42 class. + + // 42 - class for "syntax error or access rule violation" + error specific part. + // Note that Ignite specific codes start from 422 because H2 uses codes starting with 421. + case TABLE_NOT_FOUND: + return "42201"; + + case TABLE_ALREADY_EXISTS: + return "42202"; + + case INDEX_ALREADY_EXISTS: + return "42203"; + + case INDEX_NOT_FOUND: + return "42204"; + + case COLUMN_NOT_FOUND: + return "42205"; + + case COLUMN_ALREADY_EXISTS: + return "42206"; + + case STMT_TYPE_MISMATCH: + return "42207"; + + case UNEXPECTED_OPERATION: + return "42208"; + + case UNEXPECTED_ELEMENT_TYPE: + return "42209"; + + case KEY_UPDATE: + return "42210"; + + default: + return "50000"; // Generic value for custom "50" class. + } } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java index ba87cff10c9c6..fafe65373c3d1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java @@ -48,8 +48,10 @@ import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.CAX; import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.marshaller.jdk.JdkMarshaller; @@ -172,7 +174,23 @@ public class GridCacheQueryJdbcTask extends ComputeTaskAdapter { else { status = 1; - bytes = U.marshal(MARSHALLER, new SQLException(res.getException().getMessage())); + Throwable ex = res.getException(); + + SQLException sqlEx = null; + + if (X.hasCause(ex, IgniteSQLException.class)) { + while (true) { + if (ex.getCause() == null) + break; + + ex = ex.getCause(); + + if (ex instanceof IgniteSQLException) + sqlEx = ((IgniteSQLException)ex).toJdbcException(); + } + } + + bytes = U.marshal(MARSHALLER, sqlEx == null ? new SQLException(res.getException().getMessage()) : sqlEx); } byte[] packet = new byte[bytes.length + 1]; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java index 6d7ec064f42ea..3938aa14a0edb 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java @@ -85,26 +85,23 @@ public JdbcResult response() { @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException { writer.writeInt(status()); - if (status() == STATUS_SUCCESS) { - writer.writeBoolean(res != null); - - if (res != null) - res.writeBinary(writer); - } - else + if (status() != STATUS_SUCCESS) writer.writeString(error()); + writer.writeBoolean(res != null); + + if (res != null) + res.writeBinary(writer); } /** {@inheritDoc} */ @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException { status(reader.readInt()); - if (status() == STATUS_SUCCESS) { - if (reader.readBoolean()) - res = JdbcResult.readResult(reader); - } - else + if (status() != STATUS_SUCCESS) error(reader.readString()); + + if (reader.readBoolean()) + res = JdbcResult.readResult(reader); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index 660742965bee0..ef1853fa3c5be 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -22,23 +22,8 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.jetbrains.annotations.Nullable; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_ALREADY_EXISTS; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.COLUMN_NOT_FOUND; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.CONCURRENT_UPDATE; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.DUPLICATE_KEY; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_ALREADY_EXISTS; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.INDEX_NOT_FOUND; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.KEY_UPDATE; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_KEY; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.NULL_VALUE; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.PARSING; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.STMT_TYPE_MISMATCH; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_ALREADY_EXISTS; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.TABLE_NOT_FOUND; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_ELEMENT_TYPE; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNEXPECTED_OPERATION; import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNKNOWN; -import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.UNSUPPORTED_OPERATION; +import static org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode.codeToSqlState; /** * Specific exception bearing information about query processing errors for more detailed @@ -58,7 +43,7 @@ public class IgniteSQLException extends IgniteException { /** */ public IgniteSQLException(String msg) { - this(msg, UNKNOWN, null); + this(msg, UNKNOWN, (String)null); } /** @@ -77,16 +62,19 @@ public IgniteSQLException(String msg, @Nullable Throwable cause) { /** */ public IgniteSQLException(String msg, int statusCode, @Nullable Throwable cause) { - super(msg, cause); - this.sqlState = (cause instanceof SQLException ? ((SQLException) cause).getSQLState() : - codeToSqlState(statusCode)); - this.statusCode = statusCode; + this(msg, statusCode, (cause instanceof SQLException ? ((SQLException)cause).getSQLState() : + codeToSqlState(statusCode))); } /** */ public IgniteSQLException(String msg, int statusCode) { + this(msg, statusCode, codeToSqlState(statusCode)); + } + + /** */ + public IgniteSQLException(String msg, int statusCode, String sqlState) { super(msg); - this.sqlState = codeToSqlState(statusCode); + this.sqlState = sqlState; this.statusCode = statusCode; } @@ -103,65 +91,4 @@ public int statusCode() { public SQLException toJdbcException() { return new SQLException(getMessage(), sqlState, statusCode, this); } - - /** - * Map Ignite specific error code to standard SQL state. - * @param statusCode Ignite specific error code. - * @return SQL state string. - * @see Wikipedia: SQLSTATE spec. - * @see IgniteQueryErrorCode - */ - public static String codeToSqlState(int statusCode) { - switch (statusCode) { - case DUPLICATE_KEY: - return "23000"; // Generic value for "integrity constraint violation" 23 class. - - case NULL_KEY: - case NULL_VALUE: - return "22004"; // "Null value not allowed". - - case UNSUPPORTED_OPERATION: - return "0A000"; // Generic value for "feature not supported" 0A class. - - case CONCURRENT_UPDATE: - return "40000"; // Generic value for "tx rollback" 40 class. - - case PARSING: - return "42000"; // Generic value for "syntax error or access rule violation" 42 class. - - // 42 - class for "syntax error or access rule violation" + error specific part. - case TABLE_NOT_FOUND: - return "42001"; - - case TABLE_ALREADY_EXISTS: - return "42002"; - - case INDEX_ALREADY_EXISTS: - return "42003"; - - case INDEX_NOT_FOUND: - return "42004"; - - case COLUMN_NOT_FOUND: - return "42005"; - - case COLUMN_ALREADY_EXISTS: - return "42006"; - - case STMT_TYPE_MISMATCH: - return "42007"; - - case UNEXPECTED_OPERATION: - return "42008"; - - case UNEXPECTED_ELEMENT_TYPE: - return "42009"; - - case KEY_UPDATE: - return "42010"; - - default: - return "50000"; // Generic value for custom "50" class. - } - } } From e948325a40b9c727e676b9434d0fb4177e5dbb1a Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Thu, 31 Aug 2017 17:36:06 +0300 Subject: [PATCH 06/43] Added tests to suite. --- .../apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java index 691ddbf62b6cd..e6e6f76fa7511 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java @@ -25,6 +25,7 @@ import org.apache.ignite.jdbc.JdbcConnectionSelfTest; import org.apache.ignite.jdbc.JdbcDefaultNoOpCacheTest; import org.apache.ignite.jdbc.JdbcEmptyCacheSelfTest; +import org.apache.ignite.jdbc.JdbcErrorsSelfTest; import org.apache.ignite.jdbc.JdbcLocalCachesSelfTest; import org.apache.ignite.jdbc.JdbcMetadataSelfTest; import org.apache.ignite.jdbc.JdbcNoDefaultCacheTest; @@ -45,6 +46,7 @@ import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalPartitionedSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinDynamicIndexTransactionalReplicatedSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinEmptyCacheSelfTest; +import org.apache.ignite.jdbc.thin.JdbcThinErrorsSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinInsertStatementSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinMergeStatementSelfTest; import org.apache.ignite.jdbc.thin.JdbcThinMetadataSelfTest; @@ -79,6 +81,7 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcPojoQuerySelfTest.class)); suite.addTest(new TestSuite(JdbcPojoLegacyQuerySelfTest.class)); suite.addTest(new TestSuite(JdbcConnectionReopenTest.class)); + suite.addTest(new TestSuite(JdbcErrorsSelfTest.class)); // Ignite client node based driver tests suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcConnectionSelfTest.class)); @@ -103,6 +106,7 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcBlobTest.class)); suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcStreamingSelfTest.class)); + suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcErrorsSelfTest.class)); // DDL tests. suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDynamicIndexAtomicPartitionedNearSelfTest.class)); @@ -121,6 +125,7 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcThinNoDefaultSchemaTest.class)); suite.addTest(new TestSuite(JdbcThinEmptyCacheSelfTest.class)); suite.addTest(new TestSuite(JdbcThinMetadataSelfTest.class)); + suite.addTest(new TestSuite(JdbcThinErrorsSelfTest.class)); suite.addTest(new TestSuite(JdbcThinInsertStatementSelfTest.class)); suite.addTest(new TestSuite(JdbcThinUpdateStatementSelfTest.class)); From e4f630f72f28109020bb2da3b0d21428f0e00e24 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Tue, 5 Sep 2017 15:12:47 +0300 Subject: [PATCH 07/43] Review fixes 1 --- .../cache/query/IgniteQueryErrorCode.java | 27 +------------------ 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index 63b56d9f3809c..fedd1a4eaba76 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -131,43 +131,18 @@ public static String codeToSqlState(int statusCode) { case UNSUPPORTED_OPERATION: return "0A000"; // Generic value for "feature not supported" 0A class. - case CONCURRENT_UPDATE: - return "40000"; // Generic value for "tx rollback" 40 class. - case PARSING: - return "42000"; // Generic value for "syntax error or access rule violation" 42 class. - - // 42 - class for "syntax error or access rule violation" + error specific part. - // Note that Ignite specific codes start from 422 because H2 uses codes starting with 421. case TABLE_NOT_FOUND: - return "42201"; - case TABLE_ALREADY_EXISTS: - return "42202"; - case INDEX_ALREADY_EXISTS: - return "42203"; - case INDEX_NOT_FOUND: - return "42204"; - case COLUMN_NOT_FOUND: - return "42205"; - case COLUMN_ALREADY_EXISTS: - return "42206"; - case STMT_TYPE_MISMATCH: - return "42207"; - case UNEXPECTED_OPERATION: - return "42208"; - case UNEXPECTED_ELEMENT_TYPE: - return "42209"; - case KEY_UPDATE: - return "42210"; + return "42000"; default: return "50000"; // Generic value for custom "50" class. From 8376518edaa050e4fce89080948e42bd9cec2b74 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Wed, 6 Sep 2017 20:45:42 +0300 Subject: [PATCH 08/43] Fixes --- .../apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java | 8 ++++---- .../internal/processors/query/IgniteSQLException.java | 10 +++++++--- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java index 12c2923e86049..e4e5f07e760fd 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -51,8 +51,8 @@ public abstract class JdbcErrorsAbstractSelfTest extends GridCommonAbstractTest * Test that H2 specific error codes get propagated to Ignite SQL exceptions. * @throws SQLException if failed. */ - public void testH2Errors() throws SQLException { - checkErrorState("gibberish", "42001"); + public void testParsingErrors() throws SQLException { + checkErrorState("gibberish", "42000"); } /** @@ -60,7 +60,7 @@ public void testH2Errors() throws SQLException { * @throws SQLException if failed. */ public void testTableErrors() throws SQLException { - checkErrorState("DROP TABLE \"PUBLIC\".missing", "42201"); + checkErrorState("DROP TABLE \"PUBLIC\".missing", "42000"); } /** @@ -68,7 +68,7 @@ public void testTableErrors() throws SQLException { * @throws SQLException if failed. */ public void testIndexErrors() throws SQLException { - checkErrorState("DROP INDEX \"PUBLIC\".missing", "42204"); + checkErrorState("DROP INDEX \"PUBLIC\".missing", "42000"); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index ef1853fa3c5be..a324d4e1e53a1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -62,8 +62,7 @@ public IgniteSQLException(String msg, @Nullable Throwable cause) { /** */ public IgniteSQLException(String msg, int statusCode, @Nullable Throwable cause) { - this(msg, statusCode, (cause instanceof SQLException ? ((SQLException)cause).getSQLState() : - codeToSqlState(statusCode))); + this(msg, statusCode, codeToSqlState(statusCode), cause); } /** */ @@ -73,7 +72,12 @@ public IgniteSQLException(String msg, int statusCode) { /** */ public IgniteSQLException(String msg, int statusCode, String sqlState) { - super(msg); + this(msg, statusCode, sqlState, null); + } + + /** */ + private IgniteSQLException(String msg, int statusCode, String sqlState, @Nullable Throwable cause) { + super(msg, cause); this.sqlState = sqlState; this.statusCode = statusCode; } From 11c9b947cfd0e5421146606340f809496412c3d3 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Thu, 7 Sep 2017 23:34:47 +0300 Subject: [PATCH 09/43] IGNITE-5620 review fixes --- .../ignite/jdbc/JdbcErrorsSelfTest.java | 59 ---------- .../jdbc/suite/IgniteJdbcDriverTestSuite.java | 2 - .../jdbc/thin/JdbcThinConnection.java | 64 ++++++----- .../jdbc/thin/JdbcThinDatabaseMetadata.java | 50 +++++--- .../jdbc/thin/JdbcThinParameterMetadata.java | 6 +- .../jdbc/thin/JdbcThinPreparedStatement.java | 46 +++++--- .../internal/jdbc/thin/JdbcThinResultSet.java | 108 +++++++++++------- .../jdbc/thin/JdbcThinResultSetMetadata.java | 4 +- .../internal/jdbc/thin/JdbcThinStatement.java | 40 ++++--- .../ignite/internal/jdbc2/JdbcUtils.java | 48 +++++++- .../cache/query/IgniteQueryErrorCode.java | 67 +++++++++++ .../query/jdbc/GridCacheQueryJdbcTask.java | 20 +--- .../odbc/jdbc/JdbcRequestHandler.java | 5 + .../processors/odbc/jdbc/JdbcResponse.java | 7 ++ .../query/h2/DmlStatementsProcessor.java | 67 ++++++----- .../query/h2/sql/GridSqlQueryParser.java | 6 +- 16 files changed, 359 insertions(+), 240 deletions(-) delete mode 100644 modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java deleted file mode 100644 index 5b4c7004e52b9..0000000000000 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsSelfTest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.jdbc; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import org.apache.ignite.configuration.ConnectorConfiguration; -import org.apache.ignite.configuration.IgniteConfiguration; -import org.apache.ignite.spi.discovery.tcp.TcpDiscoverySpi; -import org.apache.ignite.spi.discovery.tcp.ipfinder.TcpDiscoveryIpFinder; -import org.apache.ignite.spi.discovery.tcp.ipfinder.vm.TcpDiscoveryVmIpFinder; - -/** - * Test SQLSTATE codes propagation with "legacy" driver. - */ -public class JdbcErrorsSelfTest extends JdbcErrorsAbstractSelfTest { - /** IP finder. */ - private static final TcpDiscoveryIpFinder IP_FINDER = new TcpDiscoveryVmIpFinder(true); - - /** {@inheritDoc} */ - @Override protected Connection getConnection() throws SQLException { - return DriverManager.getConnection("jdbc:ignite://127.0.0.1/test"); - } - - /** {@inheritDoc} */ - @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { - IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); - - TcpDiscoverySpi disco = new TcpDiscoverySpi(); - - disco.setIpFinder(IP_FINDER); - - cfg.setDiscoverySpi(disco); - - assert cfg.getConnectorConfiguration() == null; - - ConnectorConfiguration clientCfg = new ConnectorConfiguration(); - - cfg.setConnectorConfiguration(clientCfg); - - return cfg; - } -} diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java index fc37186e9c043..bbcfb5a7edaf7 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java @@ -25,7 +25,6 @@ import org.apache.ignite.jdbc.JdbcConnectionSelfTest; import org.apache.ignite.jdbc.JdbcDefaultNoOpCacheTest; import org.apache.ignite.jdbc.JdbcEmptyCacheSelfTest; -import org.apache.ignite.jdbc.JdbcErrorsSelfTest; import org.apache.ignite.jdbc.JdbcLocalCachesSelfTest; import org.apache.ignite.jdbc.JdbcMetadataSelfTest; import org.apache.ignite.jdbc.JdbcNoDefaultCacheTest; @@ -83,7 +82,6 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcPojoQuerySelfTest.class)); suite.addTest(new TestSuite(JdbcPojoLegacyQuerySelfTest.class)); suite.addTest(new TestSuite(JdbcConnectionReopenTest.class)); - suite.addTest(new TestSuite(JdbcErrorsSelfTest.class)); // Ignite client node based driver tests suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcConnectionSelfTest.class)); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 23235dccbbd2b..7033c20883b1d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -37,6 +37,7 @@ import java.util.Properties; import java.util.concurrent.Executor; import java.util.logging.Logger; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.util.typedef.F; import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; @@ -54,6 +55,7 @@ import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_RCV_BUF; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_SND_BUF; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_TCP_NO_DELAY; +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC connection implementation. @@ -138,7 +140,8 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ catch (Exception e) { cliIo.close(); - throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', e); + throw igniteSqlException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', + IgniteQueryErrorCode.CLIENT_CONNECTION_FAILED, e); } } @@ -186,7 +189,7 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability); if (sql == null) - throw new SQLException("SQL string cannot be null."); + throw igniteSqlException("SQL string cannot be null."); JdbcThinPreparedStatement stmt = new JdbcThinPreparedStatement(this, sql, resSetHoldability); @@ -234,7 +237,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (sql == null) - throw new SQLException("SQL string cannot be null."); + throw igniteSqlException("SQL string cannot be null."); return sql; } @@ -264,7 +267,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw new SQLException("Transaction cannot be committed explicitly in auto-commit mode."); + throw igniteSqlException("Transaction cannot be committed explicitly in auto-commit mode."); LOG.warning("Transactions are not supported."); } @@ -274,7 +277,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw new SQLException("Transaction cannot rollback in auto-commit mode."); + throw igniteSqlException("Transaction cannot rollback in auto-commit mode."); LOG.warning("Transactions are not supported."); } @@ -347,7 +350,8 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, break; default: - throw new SQLException("Invalid transaction isolation level."); + throw igniteSqlException("Invalid transaction isolation level.", + IgniteQueryErrorCode.INVALID_TRANSACTION_LEVEL); } txIsolation = level; @@ -396,7 +400,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, LOG.warning("Transactions are not supported."); if (holdability != HOLD_CURSORS_OVER_COMMIT && holdability != CLOSE_CURSORS_AT_COMMIT) - throw new SQLException("Invalid result set holdability value."); + throw igniteSqlException("Invalid result set holdability value."); this.holdability = holdability; } @@ -413,7 +417,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw new SQLException("Savepoint cannot be set in auto-commit mode."); + throw igniteSqlException("Savepoint cannot be set in auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -423,10 +427,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (name == null) - throw new SQLException("Savepoint name cannot be null."); + throw igniteSqlException("Savepoint name cannot be null."); if (autoCommit) - throw new SQLException("Savepoint cannot be set in auto-commit mode."); + throw igniteSqlException("Savepoint cannot be set in auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -436,10 +440,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (savepoint == null) - throw new SQLException("Invalid savepoint."); + throw igniteSqlException("Invalid savepoint."); if (autoCommit) - throw new SQLException("Auto-commit mode."); + throw igniteSqlException("Auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -449,7 +453,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (savepoint == null) - throw new SQLException("Savepoint cannot be null."); + throw igniteSqlException("Savepoint cannot be null."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -514,7 +518,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, /** {@inheritDoc} */ @Override public boolean isValid(int timeout) throws SQLException { if (timeout < 0) - throw new SQLException("Invalid timeout: " + timeout); + throw igniteSqlException("Invalid timeout: " + timeout); return !closed; } @@ -550,7 +554,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null."); + throw igniteSqlException("Type name cannot be null.", IgniteQueryErrorCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -560,7 +564,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null."); + throw igniteSqlException("Type name cannot be null.", IgniteQueryErrorCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -569,7 +573,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Connection is not a wrapper for " + iface.getName()); + throw igniteSqlException("Connection is not a wrapper for " + iface.getName()); return (T)this; } @@ -596,7 +600,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, /** {@inheritDoc} */ @Override public void abort(Executor executor) throws SQLException { if (executor == null) - throw new SQLException("Executor cannot be null."); + throw igniteSqlException("Executor cannot be null."); close(); } @@ -606,10 +610,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (executor == null) - throw new SQLException("Executor cannot be null."); + throw igniteSqlException("Executor cannot be null."); if (ms < 0) - throw new SQLException("Network timeout cannot be negative."); + throw igniteSqlException("Network timeout cannot be negative."); timeout = ms; } @@ -628,7 +632,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, */ private void ensureNotClosed() throws SQLException { if (closed) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); } /** @@ -652,7 +656,7 @@ private static String extractHost(Properties props) throws SQLException { host = host.trim(); if (F.isEmpty(host)) - throw new SQLException("Host name is empty."); + throw igniteSqlException("Host name is empty.", IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); return host; } @@ -676,10 +680,10 @@ private static int extractPort(Properties props) throws SQLException { port = Integer.parseInt(portStr); if (port <= 0 || port > 0xFFFF) - throw new SQLException("Invalid port: " + portStr); + throw igniteSqlException("Invalid port: " + portStr, IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); } catch (NumberFormatException e) { - throw new SQLException("Invalid port: " + portStr, e); + throw igniteSqlException("Invalid port: " + portStr, IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); } return port; @@ -705,8 +709,8 @@ private static boolean extractBoolean(Properties props, String propName, boolean else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal)) return false; else - throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']'); + throw igniteSqlException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + strVal + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); } /** @@ -722,8 +726,8 @@ private static int extractIntNonNegative(Properties props, String propName, int int res = extractInt(props, propName, dfltVal); if (res < 0) - throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + res + ']'); + throw igniteSqlException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + res + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); return res; } @@ -747,8 +751,8 @@ private static int extractInt(Properties props, String propName, int dfltVal) th return Integer.parseInt(strVal); } catch (NumberFormatException e) { - throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']'); + throw igniteSqlException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + strVal + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index b27fee6ef2e35..7a421b194876a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -32,6 +32,7 @@ import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.IgniteVersionUtils; import org.apache.ignite.internal.jdbc2.JdbcUtils; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; @@ -41,6 +42,7 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcPrimaryKeyMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcTableMeta; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; import static java.sql.Connection.TRANSACTION_NONE; @@ -48,6 +50,7 @@ import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; import static java.sql.RowIdLifetime.ROWID_UNSUPPORTED; +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC database metadata implementation. @@ -702,7 +705,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, String[] tblTypes) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -743,13 +746,16 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { return new JdbcThinResultSet(rows, meta); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -797,7 +803,7 @@ private List tableRow(JdbcTableMeta tblMeta) { @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, String colNamePtrn) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -834,13 +840,16 @@ private List tableRow(JdbcTableMeta tblMeta) { return new JdbcThinResultSet(rows, meta); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -937,7 +946,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { /** {@inheritDoc} */ @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -960,13 +969,16 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { return new JdbcThinResultSet(rows, meta); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1168,7 +1180,7 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique, boolean approximate) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1198,13 +1210,16 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { return new JdbcThinResultSet(rows, meta); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1442,7 +1457,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed."); + throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class), @@ -1468,13 +1483,16 @@ private List> indexRows(JdbcIndexMeta idxMeta) { return new JdbcThinResultSet(rows, meta); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1541,7 +1559,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Database meta data is not a wrapper for " + iface.getName()); + throw igniteSqlException("Database meta data is not a wrapper for " + iface.getName()); return (T)this; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java index 8647258f88867..5ea953f2d71fb 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java @@ -22,6 +22,8 @@ import java.util.List; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcParameterMeta; +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; + /** * JDBC SQL query's parameters metadata. */ @@ -89,7 +91,7 @@ public JdbcThinParameterMetadata(List meta) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Parameters metadata is not a wrapper for " + iface.getName()); + throw igniteSqlException("Parameters metadata is not a wrapper for " + iface.getName()); return (T)this; } @@ -108,7 +110,7 @@ public JdbcThinParameterMetadata(List meta) { */ private JdbcParameterMeta parameter(int param) throws SQLException { if (param <= 0 || param > meta.size()) - throw new SQLException("Invalid parameter number"); + throw igniteSqlException("Invalid parameter number"); return meta.get(param - 1); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index 49a1029004735..35cfda2441e33 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -41,9 +41,13 @@ import java.util.ArrayList; import java.util.Calendar; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; +import org.apache.ignite.internal.processors.query.IgniteSQLException; + +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC prepared statement implementation. @@ -78,14 +82,15 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep ResultSet rs = getResultSet(); if (rs == null) - throw new SQLException("The query isn't SELECT query: " + sql); + throw igniteSqlException("The query isn't SELECT query: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); return rs; } /** {@inheritDoc} */ @Override public ResultSet executeQuery(String sql) throws SQLException { - throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'executeQuery(String)' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @@ -95,29 +100,33 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep int res = getUpdateCount(); if (res == -1) - throw new SQLException("The query is not DML statement: " + sql); + throw igniteSqlException("The query is not DML statement: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); return res; } /** {@inheritDoc} */ @Override public int executeUpdate(String sql) throws SQLException { - throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'executeUpdate(String)' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int columnIndexes[]) throws SQLException { - throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, String columnNames[]) throws SQLException { - throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " + + "instance.", IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @@ -246,7 +255,8 @@ private void executeWithArguments() throws SQLException { /** {@inheritDoc} */ @Override public boolean execute(String sql) throws SQLException { - throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'execute(String)' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @@ -266,7 +276,8 @@ private void executeWithArguments() throws SQLException { /** {@inheritDoc} */ @Override public void addBatch(String sql) throws SQLException { - throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance."); + throw igniteSqlException("The method 'addBatch(String)' is called on PreparedStatement instance.", + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); } /** {@inheritDoc} */ @@ -345,9 +356,6 @@ private void executeWithArguments() throws SQLException { @Override public ParameterMetaData getParameterMetaData() throws SQLException { ensureNotClosed(); try { - if (conn.isClosed()) - throw new SQLException("Connection is closed."); - if (metaData != null) return metaData; @@ -357,13 +365,16 @@ private void executeWithArguments() throws SQLException { return metaData; } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -502,7 +513,7 @@ private void executeWithArguments() throws SQLException { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Prepared statement is not a wrapper for " + iface.getName()); + throw igniteSqlException("Prepared statement is not a wrapper for " + iface.getName()); return (T)this; } @@ -523,10 +534,11 @@ private void setArgument(int paramIdx, Object val) throws SQLException { ensureNotClosed(); if (val != null && !SqlListenerUtils.isPlainType(val.getClass())) - throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']'); + throw igniteSqlException("Parameter type is unsupported. [cls=" + val.getClass() + ']', + IgniteQueryErrorCode.UNSUPPORTED_PARAM_TYPE); if (paramIdx < 1) - throw new SQLException("Parameter index is invalid: " + paramIdx); + throw igniteSqlException("Parameter index is invalid: " + paramIdx); if (args == null) args = new ArrayList<>(paramIdx); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index 0a0c9780f3654..e92a78b97623e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -48,9 +48,13 @@ import java.util.List; import java.util.Map; import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; +import org.apache.ignite.internal.processors.query.IgniteSQLException; + +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC result set implementation. @@ -205,13 +209,16 @@ public class JdbcThinResultSet implements ResultSet { rowsIter = rows.iterator(); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { stmt.connection().close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", e); } } @@ -255,13 +262,16 @@ void close0() throws SQLException { closed = true; } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { stmt.connection().close(); - throw new SQLException("Failed to close Ignite query.", e); + throw igniteSqlException("Failed to close Ignite query.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to close Ignite query.", e); + throw igniteSqlException("Failed to close Ignite query.", e); } } @@ -298,11 +308,12 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()) != 0; } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to boolean: " + val, e); + throw igniteSqlException("Cannot convert to boolean: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT, + e); } } else - throw new SQLException("Cannot convert to boolean: " + val); + throw igniteSqlException("Cannot convert to boolean: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -323,11 +334,12 @@ else if (cls == String.class || cls == Character.class) { return Byte.parseByte(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to byte: " + val, e); + throw igniteSqlException("Cannot convert to byte: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to byte: " + val); + throw igniteSqlException("Cannot convert to byte: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -348,11 +360,12 @@ else if (cls == String.class || cls == Character.class) { return Short.parseShort(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to short: " + val, e); + throw igniteSqlException("Cannot convert to short: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to short: " + val); + throw igniteSqlException("Cannot convert to short: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -373,11 +386,12 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to int: " + val, e); + throw igniteSqlException("Cannot convert to int: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to int: " + val); + throw igniteSqlException("Cannot convert to int: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -398,11 +412,12 @@ else if (cls == String.class || cls == Character.class) { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to long: " + val, e); + throw igniteSqlException("Cannot convert to long: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to long: " + val); + throw igniteSqlException("Cannot convert to long: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -423,11 +438,12 @@ else if (cls == String.class || cls == Character.class) { return Float.parseFloat(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to float: " + val, e); + throw igniteSqlException("Cannot convert to float: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to float: " + val); + throw igniteSqlException("Cannot convert to float: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -448,11 +464,12 @@ else if (cls == String.class || cls == Character.class) { return Double.parseDouble(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to double: " + val, e); + throw igniteSqlException("Cannot convert to double: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + e); } } else - throw new SQLException("Cannot convert to double: " + val); + throw igniteSqlException("Cannot convert to double: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); } /** {@inheritDoc} */ @@ -494,7 +511,7 @@ else if (cls == Long.class) { else if (cls == String.class) return ((String)val).getBytes(); else - throw new SQLException("Cannot convert to byte[]: " + val); + throw igniteSqlException("Cannot convert to byte[]: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -511,7 +528,7 @@ else if (cls == String.class) else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class) return new Date(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to date: " + val); + throw igniteSqlException("Cannot convert to date: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -528,7 +545,7 @@ else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class) return new Time(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to time: " + val); + throw igniteSqlException("Cannot convert to time: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -545,7 +562,7 @@ else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class) return new Timestamp(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to timestamp: " + val); + throw igniteSqlException("Cannot convert to timestamp: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -564,11 +581,11 @@ else if (cls == String.class) { return new URL(val.toString()); } catch (MalformedURLException e) { - throw new SQLException("Cannot convert to URL: " + val, e); + throw igniteSqlException("Cannot convert to URL: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT, e); } } else - throw new SQLException("Cannot convert to URL: " + val); + throw igniteSqlException("Cannot convert to URL: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } @@ -753,7 +770,7 @@ else if (cls == String.class) { Integer order = columnOrder().get(colLb.toUpperCase()); if (order == null) - throw new SQLException("Column not found: " + colLb); + throw igniteSqlException("Column not found: " + colLb, IgniteQueryErrorCode.COLUMN_NOT_FOUND); assert order >= 0; @@ -794,11 +811,12 @@ else if (cls == String.class || cls == Character.class) { return (BigDecimal)decimalFormat.get().parse(val.toString()); } catch (ParseException e) { - throw new SQLException("Cannot convert to BigDecimal: " + val, e); + throw igniteSqlException("Cannot convert to BigDecimal: " + val, + IgniteQueryErrorCode.INVALID_VALUE_FORMAT, e); } } else - throw new SQLException("Cannot convert to BigDecimal: " + val); + throw igniteSqlException("Cannot convert to BigDecimal: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } /** {@inheritDoc} */ @@ -840,28 +858,28 @@ else if (cls == String.class || cls == Character.class) { @Override public void beforeFirst() throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public void afterLast() throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean first() throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean last() throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @@ -875,21 +893,21 @@ else if (cls == String.class || cls == Character.class) { @Override public boolean absolute(int row) throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean relative(int rows) throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean previous() throws SQLException { ensureNotClosed(); - throw new SQLException("Result set is forward-only."); + throw igniteSqlException("Result set is forward-only."); } /** {@inheritDoc} */ @@ -912,7 +930,7 @@ else if (cls == String.class || cls == Character.class) { ensureNotClosed(); if (fetchSize <= 0) - throw new SQLException("Fetch size must be greater than zero."); + throw igniteSqlException("Fetch size must be greater than zero."); this.fetchSize = fetchSize; } @@ -1272,7 +1290,7 @@ else if (cls == String.class || cls == Character.class) { ensureNotClosed(); if (getConcurrency() == CONCUR_READ_ONLY) - throw new SQLException("The result set concurrency is CONCUR_READ_ONLY"); + throw igniteSqlException("The result set concurrency is CONCUR_READ_ONLY"); } /** {@inheritDoc} */ @@ -1765,7 +1783,7 @@ else if (cls == String.class || cls == Character.class) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Result set is not a wrapper for " + iface.getName()); + throw igniteSqlException("Result set is not a wrapper for " + iface.getName()); return (T)this; } @@ -1834,7 +1852,8 @@ else if (targetCls == URL.class) if (targetCls == cls) return val; else - throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val); + throw igniteSqlException("Cannot convert to " + targetCls.getName() + ": " + val, + IgniteQueryErrorCode.INVALID_VALUE_FORMAT); } } @@ -1858,7 +1877,7 @@ private Object getValue(int colIdx) throws SQLException { return val; } catch (IndexOutOfBoundsException e) { - throw new SQLException("Invalid column index: " + colIdx, e); + throw igniteSqlException("Invalid column index: " + colIdx, IgniteQueryErrorCode.COLUMN_NOT_FOUND, e); } } @@ -1869,7 +1888,7 @@ private Object getValue(int colIdx) throws SQLException { */ private void ensureNotClosed() throws SQLException { if (closed) - throw new SQLException("Result set is closed."); + throw igniteSqlException("Result set is closed.", IgniteQueryErrorCode.INVALID_RESULT_SET_STATE); } /** @@ -1888,7 +1907,7 @@ private void ensureHasCurrentRow() throws SQLException { */ private List meta() throws SQLException { if (finished && (!isQuery || autoClose)) - throw new SQLException("Server cursor is already closed."); + throw igniteSqlException("Server cursor is already closed.", IgniteQueryErrorCode.INVALID_RESULT_SET_STATE); if (!metaInit) { try { @@ -1898,13 +1917,16 @@ private List meta() throws SQLException { metaInit = true; } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { stmt.connection().close(); - throw new SQLException("Failed to get query metadata.", e); + throw igniteSqlException("Failed to get query metadata.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to get query metadata.", e); + throw igniteSqlException("Failed to get query metadata.", e); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java index 4c560bc07464f..a17c70ecdaf74 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java @@ -22,6 +22,8 @@ import java.util.List; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; + /** * JDBC result set metadata implementation. */ @@ -149,7 +151,7 @@ public class JdbcThinResultSetMetadata implements ResultSetMetaData { /** {@inheritDoc} */ @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Result set meta data is not a wrapper for " + iface.getName()); + throw igniteSqlException("Result set meta data is not a wrapper for " + iface.getName()); return (T)this; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 0df40c708f5ed..930b8a7a66b1e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -29,6 +29,7 @@ import java.util.List; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cache.query.SqlQuery; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; @@ -38,6 +39,7 @@ import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.FETCH_FORWARD; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; +import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC statement implementation. @@ -96,7 +98,8 @@ public class JdbcThinStatement implements Statement { ResultSet rs = getResultSet(); if (rs == null) - throw new SQLException("The query isn't SELECT query: " + sql); + throw igniteSqlException("The query isn't SELECT query: " + sql, + IgniteQueryErrorCode.STMT_TYPE_MISMATCH); return rs; } @@ -119,7 +122,7 @@ protected void execute0(String sql, List args) throws SQLException { alreadyRead = false; if (sql == null || sql.isEmpty()) - throw new SQLException("SQL query is empty."); + throw igniteSqlException("SQL query is empty."); try { JdbcQueryExecuteResult res = conn.io().queryExecute(conn.getSchema(), pageSize, maxRows, @@ -136,10 +139,10 @@ protected void execute0(String sql, List args) throws SQLException { catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -150,7 +153,7 @@ protected void execute0(String sql, List args) throws SQLException { int res = getUpdateCount(); if (res == -1) - throw new SQLException("The query is not DML statememt: " + sql); + throw igniteSqlException("The query is not DML statememt: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); return res; } @@ -178,7 +181,7 @@ protected void execute0(String sql, List args) throws SQLException { ensureNotClosed(); if (max < 0) - throw new SQLException("Invalid field limit."); + throw igniteSqlException("Invalid field limit."); throw new SQLFeatureNotSupportedException("Field size limitation is not supported."); } @@ -195,7 +198,7 @@ protected void execute0(String sql, List args) throws SQLException { ensureNotClosed(); if (maxRows < 0) - throw new SQLException("Invalid max rows value."); + throw igniteSqlException("Invalid max rows value."); this.maxRows = maxRows; } @@ -217,7 +220,7 @@ protected void execute0(String sql, List args) throws SQLException { ensureNotClosed(); if (timeout < 0) - throw new SQLException("Invalid timeout value."); + throw igniteSqlException("Invalid timeout value."); this.timeout = timeout * 1000; } @@ -321,7 +324,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { ensureNotClosed(); if (fetchSize <= 0) - throw new SQLException("Fetch size must be greater than zero."); + throw igniteSqlException("Fetch size must be greater than zero."); this.pageSize = fetchSize; } @@ -377,7 +380,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { alreadyRead = false; if (batch == null || batch.isEmpty()) - throw new SQLException("Batch is empty."); + throw igniteSqlException("Batch is empty."); try { JdbcBatchExecuteResult res = conn.io().batchExecute(conn.getSchema(), batch); @@ -387,13 +390,16 @@ private JdbcThinResultSet lastResultSet() throws SQLException { return res.updateCounts(); } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } catch (IOException e) { conn.close(); - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); + throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } finally { batch = null; @@ -423,7 +429,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { break; default: - throw new SQLException("Invalid 'current' parameter."); + throw igniteSqlException("Invalid 'current' parameter."); } return false; @@ -448,7 +454,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { return executeUpdate(sql); default: - throw new SQLException("Invalid autoGeneratedKeys value"); + throw igniteSqlException("Invalid autoGeneratedKeys value"); } } @@ -477,7 +483,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { return execute(sql); default: - throw new SQLException("Invalid autoGeneratedKeys value."); + throw igniteSqlException("Invalid autoGeneratedKeys value."); } } @@ -532,7 +538,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw new SQLException("Statement is not a wrapper for " + iface.getName()); + throw igniteSqlException("Statement is not a wrapper for " + iface.getName()); return (T)this; } @@ -582,6 +588,6 @@ JdbcThinConnection connection() { */ protected void ensureNotClosed() throws SQLException { if (isClosed()) - throw new SQLException("Statement is closed."); + throw igniteSqlException("Statement is closed."); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java index 37304fc960589..a620b7d194582 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java @@ -18,11 +18,13 @@ package org.apache.ignite.internal.jdbc2; import java.net.URL; +import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Date; - +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.QueryUtils; import static java.sql.Types.BIGINT; @@ -141,4 +143,48 @@ public static boolean nullable(String name, String cls) { static boolean isSqlType(Class cls) { return QueryUtils.isSqlType(cls) || cls == URL.class; } + + /** + * Create {@link SQLException} with proper {@code STATE} from given message and Ignite error code. + * @param msg error message. + * @param code error code. + * @return JDBC {@link SQLException}. + * @see IgniteQueryErrorCode + */ + public static SQLException igniteSqlException(String msg, int code) { + return new IgniteSQLException(msg, code).toJdbcException(); + } + + /** + * Create {@link SQLException} with proper {@code STATE} from given message, Ignite error code, and cause. + * @param msg error message. + * @param code error code. + * @param err cause. + * @return JDBC {@link SQLException}. + * @see IgniteQueryErrorCode + */ + public static SQLException igniteSqlException(String msg, int code, Throwable err) { + return new IgniteSQLException(msg, code, err).toJdbcException(); + } + + /** + * Create {@link SQLException} with common {@code STATE} and error code from given message. + * @param msg error message. + * @return JDBC {@link SQLException}. + * @see IgniteQueryErrorCode + */ + public static SQLException igniteSqlException(String msg) { + return new IgniteSQLException(msg).toJdbcException(); + } + + /** + * Create {@link SQLException} with common {@code STATE} and error code from given message and cause. + * @param msg error message. + * @param err cause. + * @return JDBC {@link SQLException}. + * @see IgniteQueryErrorCode + */ + public static SQLException igniteSqlException(String msg, Throwable err) { + return new IgniteSQLException(msg, err).toJdbcException(); + } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index fedd1a4eaba76..c707c574a736f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.processors.cache.query; +import java.sql.ResultSet; import java.sql.SQLException; import javax.cache.processor.EntryProcessor; import org.apache.ignite.IgniteCache; @@ -76,6 +77,24 @@ public final class IgniteQueryErrorCode { /** Required column already exists. */ public final static int COLUMN_ALREADY_EXISTS = 3009; + /** Parameter type is not supported. */ + public final static int UNSUPPORTED_PARAM_TYPE = 3010; + + /** Invalid transaction level. */ + public final static int INVALID_TRANSACTION_LEVEL = 3011; + + /** Invalid data type. */ + public final static int INVALID_DATA_TYPE = 3012; + + /** Conversion failure. */ + public final static int CONVERSION_FAILED = 3013; + + /** Invalid number format. */ + public final static int INVALID_NUMBER_FORMAT = 3014; + + /** Value can't be converted to expected type (to be used in {@link ResultSet}'s {@code getXxx()} methods. */ + public final static int INVALID_VALUE_FORMAT = 3015; + /* 4xxx - cache related runtime errors */ /** Attempt to INSERT a key that is already in cache. */ @@ -96,6 +115,23 @@ public final class IgniteQueryErrorCode { /** Cache not found. */ public final static int CACHE_NOT_FOUND = 4006; + /* 5xxx - codes for primary use by JDBC driver. */ + + /** IO error during communication. */ + public final static int CONNECTION_FAILURE = 5001; + + /** Connect. */ + public final static int CONNECTION_CLOSED = 5002; + + /** Client failed to open connection. */ + public final static int CLIENT_CONNECTION_FAILED = 5003; + + /** General connection establishment error. */ + public final static int CONNECTION_ERROR_GENERAL = 5004; + + /** Invalid result set state. */ + public final static int INVALID_RESULT_SET_STATE = 5005; + /** */ private IgniteQueryErrorCode() { // No-op. @@ -131,6 +167,37 @@ public static String codeToSqlState(int statusCode) { case UNSUPPORTED_OPERATION: return "0A000"; // Generic value for "feature not supported" 0A class. + case CONNECTION_ERROR_GENERAL: + return "08000"; + + case CLIENT_CONNECTION_FAILED: + return "08001"; // "SQL-client unable to establish SQL-connection" + + case CONNECTION_CLOSED: + return "08003"; // "Connection does not exist" + + case CONNECTION_FAILURE: + return "08006"; // "Connection failure" + + case UNSUPPORTED_PARAM_TYPE: + return "22023"; // "Invalid parameter value" + + case INVALID_TRANSACTION_LEVEL: + return "0700E"; // "Invalid LEVEL value" + + case INVALID_DATA_TYPE: + return "0D000"; // "Invalid target type specification" + + case CONVERSION_FAILED: + return "0700B"; // "Data type transform function violation" + + case INVALID_NUMBER_FORMAT: + case INVALID_VALUE_FORMAT: + return "22000"; // "Data exception" + + case INVALID_RESULT_SET_STATE: + return "24000"; // "Invalid cursor state" + case PARSING: case TABLE_NOT_FOUND: case TABLE_ALREADY_EXISTS: diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java index fafe65373c3d1..ba87cff10c9c6 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/jdbc/GridCacheQueryJdbcTask.java @@ -48,10 +48,8 @@ import org.apache.ignite.internal.managers.discovery.GridDiscoveryManager; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.CAX; import org.apache.ignite.internal.util.typedef.F; -import org.apache.ignite.internal.util.typedef.X; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.marshaller.Marshaller; import org.apache.ignite.marshaller.jdk.JdkMarshaller; @@ -174,23 +172,7 @@ public class GridCacheQueryJdbcTask extends ComputeTaskAdapter { else { status = 1; - Throwable ex = res.getException(); - - SQLException sqlEx = null; - - if (X.hasCause(ex, IgniteSQLException.class)) { - while (true) { - if (ex.getCause() == null) - break; - - ex = ex.getCause(); - - if (ex instanceof IgniteSQLException) - sqlEx = ((IgniteSQLException)ex).toJdbcException(); - } - } - - bytes = U.marshal(MARSHALLER, sqlEx == null ? new SQLException(res.getException().getMessage()) : sqlEx); + bytes = U.marshal(MARSHALLER, new SQLException(res.getException().getMessage())); } byte[] packet = new byte[bytes.length + 1]; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index 97409e39b20e3..f918f867e9380 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -647,6 +647,11 @@ private static boolean matches(String str, String ptrn) { str.matches(ptrn.replace("%", ".*").replace("_", "."))); } + /** + * Extract {@link SQLException} from given {@link Exception}, and form {@link JdbcErrorResult}, if possible. + * @param e Exception to convert. + * @return resulting {@link JdbcErrorResult}, or {@code null} if conversion wasn't possible. + */ private JdbcErrorResult exceptionToResult(Exception e) { if (!errorResponses) return null; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java index 3938aa14a0edb..0d90b67861400 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java @@ -61,6 +61,13 @@ public JdbcResponse(int status, @Nullable String err) { assert status != STATUS_SUCCESS; } + /** + * Constructor for arbitrary response. + * + * @param res result. + * @param status status code. + * @param err optional error message. + */ public JdbcResponse(JdbcResult res, int status, @Nullable String err) { super(status, err); diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java index 0ff9cfef6b60a..e8d3ea1a5af1c 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java @@ -661,48 +661,53 @@ private static Object convert(Object val, GridH2RowDescriptor desc, Class exp Class currCls = val.getClass(); - if (val instanceof Date && currCls != Date.class && expCls == Date.class) { - // H2 thinks that java.util.Date is always a Timestamp, while binary marshaller expects - // precise Date instance. Let's satisfy it. - return new Date(((Date) val).getTime()); - } + try { + if (val instanceof Date && currCls != Date.class && expCls == Date.class) { + // H2 thinks that java.util.Date is always a Timestamp, while binary marshaller expects + // precise Date instance. Let's satisfy it. + return new Date(((Date) val).getTime()); + } - // User-given UUID is always serialized by H2 to byte array, so we have to deserialize manually - if (type == Value.UUID && currCls == byte[].class) - return U.unmarshal(desc.context().marshaller(), (byte[]) val, - U.resolveClassLoader(desc.context().gridConfig())); + // User-given UUID is always serialized by H2 to byte array, so we have to deserialize manually + if (type == Value.UUID && currCls == byte[].class) + return U.unmarshal(desc.context().marshaller(), (byte[]) val, + U.resolveClassLoader(desc.context().gridConfig())); - if (LocalDateTimeUtils.isJava8DateApiPresent()) { - if (val instanceof Timestamp && LocalDateTimeUtils.isLocalDateTime(expCls)) - return LocalDateTimeUtils.valueToLocalDateTime(ValueTimestamp.get((Timestamp)val)); + if (LocalDateTimeUtils.isJava8DateApiPresent()) { + if (val instanceof Timestamp && LocalDateTimeUtils.isLocalDateTime(expCls)) + return LocalDateTimeUtils.valueToLocalDateTime(ValueTimestamp.get((Timestamp) val)); - if (val instanceof Date && LocalDateTimeUtils.isLocalDate(expCls)) - return LocalDateTimeUtils.valueToLocalDate(ValueDate.fromDateValue( - DateTimeUtils.dateValueFromDate(((Date)val).getTime()))); + if (val instanceof Date && LocalDateTimeUtils.isLocalDate(expCls)) + return LocalDateTimeUtils.valueToLocalDate(ValueDate.fromDateValue( + DateTimeUtils.dateValueFromDate(((Date) val).getTime()))); - if (val instanceof Time && LocalDateTimeUtils.isLocalTime(expCls)) - return LocalDateTimeUtils.valueToLocalTime(ValueTime.get((Time)val)); - } + if (val instanceof Time && LocalDateTimeUtils.isLocalTime(expCls)) + return LocalDateTimeUtils.valueToLocalTime(ValueTime.get((Time) val)); + } - // We have to convert arrays of reference types manually - see https://issues.apache.org/jira/browse/IGNITE-4327 - // Still, we only can convert from Object[] to something more precise. - if (type == Value.ARRAY && currCls != expCls) { - if (currCls != Object[].class) - throw new IgniteCheckedException("Unexpected array type - only conversion from Object[] is assumed"); + // We have to convert arrays of reference types manually - see https://issues.apache.org/jira/browse/IGNITE-4327 + // Still, we only can convert from Object[] to something more precise. + if (type == Value.ARRAY && currCls != expCls) { + if (currCls != Object[].class) + throw new IgniteCheckedException("Unexpected array type - only conversion from Object[] is assumed"); - // Why would otherwise type be Value.ARRAY? - assert expCls.isArray(); + // Why would otherwise type be Value.ARRAY? + assert expCls.isArray(); - Object[] curr = (Object[]) val; + Object[] curr = (Object[]) val; - Object newArr = Array.newInstance(expCls.getComponentType(), curr.length); + Object newArr = Array.newInstance(expCls.getComponentType(), curr.length); - System.arraycopy(curr, 0, newArr, 0, curr.length); + System.arraycopy(curr, 0, newArr, 0, curr.length); - return newArr; - } + return newArr; + } - return H2Utils.convert(val, desc, type); + return H2Utils.convert(val, desc, type); + } + catch (Exception e) { + throw new IgniteSQLException("Value conversion failed.", IgniteQueryErrorCode.CACHE_NOT_FOUND, e); + } } /** diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 97e9d5dd617a7..98767d7cdfe1b 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -937,7 +937,8 @@ private GridSqlCreateTable parseCreateTable(CreateTable createTbl) { int valColsNum = cols.size() - pkCols.size(); if (valColsNum == 0) - throw new IgniteSQLException("No cache value related columns found"); + throw new IgniteSQLException("No cache value related columns found", + IgniteQueryErrorCode.PARSING); res.columns(cols); res.primaryKeyColumns(pkCols); @@ -1011,7 +1012,8 @@ private GridSqlStatement parseAlterColumn(AlterTableAlterColumn stmt) { return parseAddColumn(stmt); default: - throw new IgniteSQLException("Unsupported operation code: " + stmt.getType()); + throw new IgniteSQLException("Unsupported operation code: " + stmt.getType(), + IgniteQueryErrorCode.UNSUPPORTED_OPERATION); } } From 5070e91d77ca1849fc7e9eaf5caf0e12af1fdc57 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Fri, 8 Sep 2017 15:33:35 +0300 Subject: [PATCH 10/43] IGNITE-5620 tests --- .../jdbc/JdbcErrorsAbstractSelfTest.java | 70 ++- .../jdbc/thin/JdbcThinErrorsSelfTest.java | 434 ++++++++++++++++++ 2 files changed, 492 insertions(+), 12 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java index e4e5f07e760fd..e942090ddf677 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -77,6 +77,16 @@ public void testIndexErrors() throws SQLException { */ public void testDmlErrors() throws SQLException { checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, null)", "22004"); + + checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, 'zzz')", "22004"); + } + + /** + * Test error code for the case when user attempts to refer a future currently unsupported. + * @throws SQLException if failed. + */ + public void testUnsupportedSql() throws SQLException { + checkErrorState("ALTER TABLE \"test\".Integer DROP COLUMN _key", "0A000"); } /** @@ -92,21 +102,57 @@ public void testDmlErrors() throws SQLException { * @throws SQLException if failed. */ @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - private void checkErrorState(String sql, String expState) throws SQLException { - try (Connection conn = getConnection()) { - try (final PreparedStatement stmt = conn.prepareStatement(sql)) { - SQLException ex = (SQLException)GridTestUtils.assertThrows(null, new IgniteCallable() { - @Override public Void call() throws Exception { - stmt.execute(); + private void checkErrorState(final String sql, String expState) throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (final PreparedStatement stmt = conn.prepareStatement(sql)) { + stmt.execute(); + } + } + }, expState); + } - fail(); + /** + * Test that running given closure yields expected SQLSTATE code. + * @param clo closure. + * @param expState expected SQLSTATE code. + * @throws SQLException if failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + protected void checkErrorState(final ConnClosure clo, String expState) throws SQLException { + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + try (final Connection conn = getConnection()) { + clo.run(conn); - return null; - } - }, SQLException.class, null); + fail(); - assertEquals(expState, ex.getSQLState()); + return null; + } } - } + }, expState); + } + + /** + * Test that running given closure yields expected SQLSTATE code. + * @param clo closure. + * @param expState expected SQLSTATE code. + * @throws SQLException if failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + protected void checkErrorState(final IgniteCallable clo, String expState) throws SQLException { + SQLException ex = (SQLException)GridTestUtils.assertThrows(null, clo, SQLException.class, null); + + assertEquals(expState, ex.getSQLState()); + } + + /** + * Runnable that accepts a {@link Connection} and can throw an exception. + */ + protected interface ConnClosure { + /** + * @throws Exception On error. + */ + void run(Connection conn) throws Exception; } } diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java index 86cc341835f96..543a93ae28a27 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java @@ -17,10 +17,19 @@ package org.apache.ignite.jdbc.thin; +import java.net.URL; import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.Date; import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; import java.sql.SQLException; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.List; import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; +import org.apache.ignite.lang.IgniteCallable; /** * Test SQLSTATE codes propagation with thin client driver. @@ -30,4 +39,429 @@ public class JdbcThinErrorsSelfTest extends JdbcErrorsAbstractSelfTest { @Override protected Connection getConnection() throws SQLException { return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1"); } + + /** + * Test error code for the case when connection string is fine but client can't reach server + * due to communication problems (not due to clear misconfiguration). + * @throws SQLException if failed. + */ + public void testConnectionError() throws SQLException { + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + DriverManager.getConnection("jdbc:ignite:thin://unknown.host"); + + return null; + } + }, "08001"); + } + + /** + * Test error code for the case when connection string is a mess. + * @throws SQLException if failed. + */ + public void testInvalidConnectionStringFormat() throws SQLException { + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + // Invalid port number yields an error. + DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:1000000"); + + return null; + } + }, "08000"); + } + + /* ALL TESTS PAST THIS POINT MUST BE MOVED TO PARENT CLASS JdbcErrorsAbstractSelfTest + * ONCE ERROR CODES RELATED WORK ON JDBC2 DRIVER IS FINISHED */ + + /** + * Test error code for the case when user attempts to use a closed connection. + * @throws SQLException if failed. + */ + public void testConnectionClosed() throws SQLException { + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + conn.close(); + + conn.prepareStatement("SELECT 1"); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + conn.close(); + + conn.createStatement(); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + conn.close(); + + conn.getMetaData(); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + + conn.close(); + + meta.getIndexInfo(null, null, null, false, false); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + + conn.close(); + + meta.getColumns(null, null, null, null); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + + conn.close(); + + meta.getPrimaryKeys(null, null, null); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + + conn.close(); + + meta.getSchemas(null, null); + + return null; + } + }, "08003"); + + checkErrorState(new IgniteCallable() { + @Override public Void call() throws Exception { + Connection conn = getConnection(); + + DatabaseMetaData meta = conn.getMetaData(); + + conn.close(); + + meta.getTables(null, null, null, null); + + return null; + } + }, "08003"); + } + + /** + * Test error code for the case when user attempts to use a closed result set. + * @throws SQLException if failed. + */ + public void testResultSetClosed() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 1")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.close(); + + rs.getInt(1); + } + } + }, "24000"); + } + + /** + * Test error code for the case when user attempts to set an invalid isolation level to a connection. + * @throws SQLException if failed. + */ + @SuppressWarnings("MagicConstant") + public void testInvalidIsolationLevel() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + conn.setTransactionIsolation(1000); + } + }, "0700E"); + } + + /** + * Test error code for the case when user attempts to get {@code int} value + * from column whose value can't be converted to an {@code int}. + * @throws SQLException if failed. + */ + public void testInvalidIntFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getLong(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code long} value + * from column whose value can't be converted to an {@code long}. + * @throws SQLException if failed. + */ + public void testInvalidLongFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getLong(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code float} value + * from column whose value can't be converted to an {@code float}. + * @throws SQLException if failed. + */ + public void testInvalidFloatFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getFloat(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code double} value + * from column whose value can't be converted to an {@code double}. + * @throws SQLException if failed. + */ + public void testInvalidDoubleFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getDouble(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code byte} value + * from column whose value can't be converted to an {@code byte}. + * @throws SQLException if failed. + */ + public void testInvalidByteFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getByte(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code short} value + * from column whose value can't be converted to an {@code short}. + * @throws SQLException if failed. + */ + public void testInvalidShortFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getShort(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code BigDecimal} value + * from column whose value can't be converted to an {@code BigDecimal}. + * @throws SQLException if failed. + */ + public void testInvalidBigDecimalFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getBigDecimal(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code boolean} value + * from column whose value can't be converted to an {@code boolean}. + * @throws SQLException if failed. + */ + public void testInvalidBooleanFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getBoolean(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@code boolean} value + * from column whose value can't be converted to an {@code boolean}. + * @throws SQLException if failed. + */ + public void testInvalidObjectFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getObject(1, List.class); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@link Date} value + * from column whose value can't be converted to a {@link Date}. + * @throws SQLException if failed. + */ + public void testInvalidDateFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getDate(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@link Time} value + * from column whose value can't be converted to a {@link Time}. + * @throws SQLException if failed. + */ + public void testInvalidTimeFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getTime(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@link Timestamp} value + * from column whose value can't be converted to a {@link Timestamp}. + * @throws SQLException if failed. + */ + public void testInvalidTimestampFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getTimestamp(1); + } + } + }, "22000"); + } + + /** + * Test error code for the case when user attempts to get {@link URL} value + * from column whose value can't be converted to a {@link URL}. + * @throws SQLException if failed. + */ + public void testInvalidUrlFormat() throws SQLException { + checkErrorState(new ConnClosure() { + @Override public void run(Connection conn) throws Exception { + try (PreparedStatement stmt = conn.prepareStatement("SELECT 'zzz'")) { + ResultSet rs = stmt.executeQuery(); + + rs.next(); + + rs.getURL(1); + } + } + }, "22000"); + } } From 37db2767fbd7f01cbc958973e0cdfc69206d3ab0 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Mon, 11 Sep 2017 21:18:44 +0300 Subject: [PATCH 11/43] Review fixes - 1. --- .../processors/query/IgniteSQLException.java | 46 ++++++++++++++++--- .../query/h2/DmlStatementsProcessor.java | 2 +- .../query/h2/sql/GridSqlQueryParser.java | 35 ++++++++++++-- 3 files changed, 70 insertions(+), 13 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index a324d4e1e53a1..e20bbe871e944 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -41,13 +41,17 @@ public class IgniteSQLException extends IgniteException { /** Code to return as {@link SQLException#vendorCode} */ private final int statusCode; - /** */ + /** + * Constructor. + * @param msg Exception message. + */ public IgniteSQLException(String msg) { this(msg, UNKNOWN, (String)null); } /** - * Minimalistic ctor accepting only {@link SQLException} as the cause. + * Constructor. + * @param cause Cause to throw this exception. */ public IgniteSQLException(SQLException cause) { super(cause); @@ -55,27 +59,55 @@ public IgniteSQLException(SQLException cause) { this.statusCode = UNKNOWN; } - /** */ + /** + * Constructor. + * @param msg Exception message. + * @param cause Cause to throw this exception. + */ public IgniteSQLException(String msg, @Nullable Throwable cause) { this(msg, UNKNOWN, cause); } - /** */ + /** + * Constructor. + * @param msg Exception message. + * @param statusCode Ignite specific error code. + * @param cause Cause to throw this exception. + * @see IgniteQueryErrorCode + */ public IgniteSQLException(String msg, int statusCode, @Nullable Throwable cause) { this(msg, statusCode, codeToSqlState(statusCode), cause); } - /** */ + /** + * Constructor. + * @param msg Exception message. + * @param statusCode Ignite specific error code. + * @see IgniteQueryErrorCode + */ public IgniteSQLException(String msg, int statusCode) { this(msg, statusCode, codeToSqlState(statusCode)); } - /** */ + /** + * Constructor. + * @param msg Exception message. + * @param statusCode Ignite specific error code. + * @param sqlState SQLSTATE standard code. + * @see IgniteQueryErrorCode + */ public IgniteSQLException(String msg, int statusCode, String sqlState) { this(msg, statusCode, sqlState, null); } - /** */ + /** + * Constructor. + * @param msg Exception message. + * @param statusCode Ignite specific error code. + * @param sqlState SQLSTATE standard code. + * @param cause Cause to throw this exception. + * @see IgniteQueryErrorCode + */ private IgniteSQLException(String msg, int statusCode, String sqlState, @Nullable Throwable cause) { super(msg, cause); this.sqlState = sqlState; diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java index e8d3ea1a5af1c..ffde06b15ad12 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java @@ -706,7 +706,7 @@ private static Object convert(Object val, GridH2RowDescriptor desc, Class exp return H2Utils.convert(val, desc, type); } catch (Exception e) { - throw new IgniteSQLException("Value conversion failed.", IgniteQueryErrorCode.CACHE_NOT_FOUND, e); + throw new IgniteSQLException("Value conversion failed.", IgniteQueryErrorCode.CONVERSION_FAILED, e); } } diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 98767d7cdfe1b..d4383bd4e5bb5 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -937,8 +937,8 @@ private GridSqlCreateTable parseCreateTable(CreateTable createTbl) { int valColsNum = cols.size() - pkCols.size(); if (valColsNum == 0) - throw new IgniteSQLException("No cache value related columns found", - IgniteQueryErrorCode.PARSING); + throw new IgniteSQLException("Tables with only key related columns are not supported at the moment", + IgniteQueryErrorCode.UNSUPPORTED_OPERATION); res.columns(cols); res.primaryKeyColumns(pkCols); @@ -1011,9 +1011,34 @@ private GridSqlStatement parseAlterColumn(AlterTableAlterColumn stmt) { case CommandInterface.ALTER_TABLE_ADD_COLUMN: return parseAddColumn(stmt); - default: - throw new IgniteSQLException("Unsupported operation code: " + stmt.getType(), - IgniteQueryErrorCode.UNSUPPORTED_OPERATION); + default: { + String stmtName = null; + + switch (stmt.getType()) { + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_CHANGE_TYPE: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_DEFAULT: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_NOT_NULL: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_RENAME: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_NULL: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY: + case CommandInterface.ALTER_TABLE_ALTER_COLUMN_VISIBILITY: + stmtName = "ALTER COLUMN"; + break; + + case CommandInterface.ALTER_TABLE_DROP_COLUMN: + stmtName = "DROP COLUMN"; + break; + } + + if (stmtName == null) { + throw new IgniteSQLException("Unsupported operation code: " + stmt.getType(), + IgniteQueryErrorCode.UNSUPPORTED_OPERATION); + } + else { + throw new IgniteSQLException("Unsupported ALTER TABLE operation: " + stmtName, + IgniteQueryErrorCode.UNSUPPORTED_OPERATION); + } + } } } From 00cca1a850ec01932792956c815fe3feff8e946e Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Tue, 12 Sep 2017 21:59:55 +0300 Subject: [PATCH 12/43] Review fixes - 2. --- .../jdbc/thin/JdbcThinConnection.java | 66 +++++++------ .../jdbc/thin/JdbcThinDatabaseMetadata.java | 35 ++++--- .../jdbc/thin/JdbcThinParameterMetadata.java | 6 +- .../jdbc/thin/JdbcThinPreparedStatement.java | 48 +++++----- .../internal/jdbc/thin/JdbcThinResultSet.java | 96 +++++++++---------- .../jdbc/thin/JdbcThinResultSetMetadata.java | 4 +- .../internal/jdbc/thin/JdbcThinStatement.java | 38 ++++---- .../ignite/internal/jdbc2/JdbcStateCode.java | 65 +++++++++++++ .../ignite/internal/jdbc2/JdbcUtils.java | 47 --------- .../cache/query/IgniteQueryErrorCode.java | 66 +------------ 10 files changed, 207 insertions(+), 264 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 7033c20883b1d..e15a02d691a53 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -37,7 +37,7 @@ import java.util.Properties; import java.util.concurrent.Executor; import java.util.logging.Logger; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.util.typedef.F; import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; @@ -55,7 +55,6 @@ import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_RCV_BUF; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_SOCK_SND_BUF; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_TCP_NO_DELAY; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC connection implementation. @@ -140,8 +139,8 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ catch (Exception e) { cliIo.close(); - throw igniteSqlException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', - IgniteQueryErrorCode.CLIENT_CONNECTION_FAILED, e); + throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', + JdbcStateCode.CLIENT_CONNECTION_FAILED, e); } } @@ -189,7 +188,7 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ checkCursorOptions(resSetType, resSetConcurrency, resSetHoldability); if (sql == null) - throw igniteSqlException("SQL string cannot be null."); + throw new SQLException("SQL string cannot be null."); JdbcThinPreparedStatement stmt = new JdbcThinPreparedStatement(this, sql, resSetHoldability); @@ -237,7 +236,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (sql == null) - throw igniteSqlException("SQL string cannot be null."); + throw new SQLException("SQL string cannot be null."); return sql; } @@ -267,7 +266,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw igniteSqlException("Transaction cannot be committed explicitly in auto-commit mode."); + throw new SQLException("Transaction cannot be committed explicitly in auto-commit mode."); LOG.warning("Transactions are not supported."); } @@ -277,7 +276,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw igniteSqlException("Transaction cannot rollback in auto-commit mode."); + throw new SQLException("Transaction cannot rollback in auto-commit mode."); LOG.warning("Transactions are not supported."); } @@ -350,8 +349,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, break; default: - throw igniteSqlException("Invalid transaction isolation level.", - IgniteQueryErrorCode.INVALID_TRANSACTION_LEVEL); + throw new SQLException("Invalid transaction isolation level.", JdbcStateCode.INVALID_TRANSACTION_LEVEL); } txIsolation = level; @@ -400,7 +398,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, LOG.warning("Transactions are not supported."); if (holdability != HOLD_CURSORS_OVER_COMMIT && holdability != CLOSE_CURSORS_AT_COMMIT) - throw igniteSqlException("Invalid result set holdability value."); + throw new SQLException("Invalid result set holdability value."); this.holdability = holdability; } @@ -417,7 +415,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (autoCommit) - throw igniteSqlException("Savepoint cannot be set in auto-commit mode."); + throw new SQLException("Savepoint cannot be set in auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -427,10 +425,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (name == null) - throw igniteSqlException("Savepoint name cannot be null."); + throw new SQLException("Savepoint name cannot be null."); if (autoCommit) - throw igniteSqlException("Savepoint cannot be set in auto-commit mode."); + throw new SQLException("Savepoint cannot be set in auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -440,10 +438,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (savepoint == null) - throw igniteSqlException("Invalid savepoint."); + throw new SQLException("Invalid savepoint."); if (autoCommit) - throw igniteSqlException("Auto-commit mode."); + throw new SQLException("Auto-commit mode."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -453,7 +451,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (savepoint == null) - throw igniteSqlException("Savepoint cannot be null."); + throw new SQLException("Savepoint cannot be null."); throw new SQLFeatureNotSupportedException("Savepoints are not supported."); } @@ -518,7 +516,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, /** {@inheritDoc} */ @Override public boolean isValid(int timeout) throws SQLException { if (timeout < 0) - throw igniteSqlException("Invalid timeout: " + timeout); + throw new SQLException("Invalid timeout: " + timeout); return !closed; } @@ -554,7 +552,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw igniteSqlException("Type name cannot be null.", IgniteQueryErrorCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null.", JdbcStateCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -564,7 +562,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw igniteSqlException("Type name cannot be null.", IgniteQueryErrorCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null.", JdbcStateCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -573,7 +571,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Connection is not a wrapper for " + iface.getName()); + throw new SQLException("Connection is not a wrapper for " + iface.getName()); return (T)this; } @@ -600,7 +598,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, /** {@inheritDoc} */ @Override public void abort(Executor executor) throws SQLException { if (executor == null) - throw igniteSqlException("Executor cannot be null."); + throw new SQLException("Executor cannot be null."); close(); } @@ -610,10 +608,10 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (executor == null) - throw igniteSqlException("Executor cannot be null."); + throw new SQLException("Executor cannot be null."); if (ms < 0) - throw igniteSqlException("Network timeout cannot be negative."); + throw new SQLException("Network timeout cannot be negative."); timeout = ms; } @@ -632,7 +630,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, */ private void ensureNotClosed() throws SQLException { if (closed) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); } /** @@ -656,7 +654,7 @@ private static String extractHost(Properties props) throws SQLException { host = host.trim(); if (F.isEmpty(host)) - throw igniteSqlException("Host name is empty.", IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Host name is empty.", JdbcStateCode.CONNECTION_ERROR); return host; } @@ -680,10 +678,10 @@ private static int extractPort(Properties props) throws SQLException { port = Integer.parseInt(portStr); if (port <= 0 || port > 0xFFFF) - throw igniteSqlException("Invalid port: " + portStr, IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Invalid port: " + portStr, JdbcStateCode.CONNECTION_ERROR); } catch (NumberFormatException e) { - throw igniteSqlException("Invalid port: " + portStr, IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Invalid port: " + portStr, JdbcStateCode.CONNECTION_ERROR); } return port; @@ -709,8 +707,8 @@ private static boolean extractBoolean(Properties props, String propName, boolean else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal)) return false; else - throw igniteSqlException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + strVal + ']', JdbcStateCode.CONNECTION_ERROR); } /** @@ -726,8 +724,8 @@ private static int extractIntNonNegative(Properties props, String propName, int int res = extractInt(props, propName, dfltVal); if (res < 0) - throw igniteSqlException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + res + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + res + ']', JdbcStateCode.CONNECTION_ERROR); return res; } @@ -751,8 +749,8 @@ private static int extractInt(Properties props, String propName, int dfltVal) th return Integer.parseInt(strVal); } catch (NumberFormatException e) { - throw igniteSqlException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', IgniteQueryErrorCode.CONNECTION_ERROR_GENERAL); + throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + + ", value=" + strVal + ']', JdbcStateCode.CONNECTION_ERROR); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index bb88fa4d331bf..a5b3bc1599d87 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -31,8 +31,8 @@ import java.util.List; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.IgniteVersionUtils; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.jdbc2.JdbcUtils; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; @@ -50,7 +50,6 @@ import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; import static java.sql.RowIdLifetime.ROWID_UNSUPPORTED; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC database metadata implementation. @@ -708,7 +707,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, String[] tblTypes) throws SQLException { if (conn.isClosed()) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -755,10 +754,10 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -806,7 +805,7 @@ private List tableRow(JdbcTableMeta tblMeta) { @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, String colNamePtrn) throws SQLException { if (conn.isClosed()) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -849,10 +848,10 @@ private List tableRow(JdbcTableMeta tblMeta) { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -949,7 +948,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { /** {@inheritDoc} */ @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { if (conn.isClosed()) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -978,10 +977,10 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1183,7 +1182,7 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique, boolean approximate) throws SQLException { if (conn.isClosed()) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1219,10 +1218,10 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1460,7 +1459,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException { if (conn.isClosed()) - throw igniteSqlException("Connection is closed.", IgniteQueryErrorCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class), @@ -1492,10 +1491,10 @@ private List> indexRows(JdbcIndexMeta idxMeta) { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -1562,7 +1561,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Database meta data is not a wrapper for " + iface.getName()); + throw new SQLException("Database meta data is not a wrapper for " + iface.getName()); return (T)this; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java index 5ea953f2d71fb..8647258f88867 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinParameterMetadata.java @@ -22,8 +22,6 @@ import java.util.List; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcParameterMeta; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; - /** * JDBC SQL query's parameters metadata. */ @@ -91,7 +89,7 @@ public JdbcThinParameterMetadata(List meta) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Parameters metadata is not a wrapper for " + iface.getName()); + throw new SQLException("Parameters metadata is not a wrapper for " + iface.getName()); return (T)this; } @@ -110,7 +108,7 @@ public JdbcThinParameterMetadata(List meta) { */ private JdbcParameterMeta parameter(int param) throws SQLException { if (param <= 0 || param > meta.size()) - throw igniteSqlException("Invalid parameter number"); + throw new SQLException("Invalid parameter number"); return meta.get(param - 1); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index 7c1496c2e5817..9ed6a2e92b967 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -41,15 +41,13 @@ import java.util.ArrayList; import java.util.Calendar; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; import org.apache.ignite.internal.processors.query.IgniteSQLException; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; - /** * JDBC prepared statement implementation. */ @@ -83,15 +81,15 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep ResultSet rs = getResultSet(); if (rs == null) - throw igniteSqlException("The query isn't SELECT query: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The query isn't SELECT query: " + sql, JdbcStateCode.PARSING_EXCEPTION); return rs; } /** {@inheritDoc} */ @Override public ResultSet executeQuery(String sql) throws SQLException { - throw igniteSqlException("The method 'executeQuery(String)' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -101,33 +99,33 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep int res = getUpdateCount(); if (res == -1) - throw igniteSqlException("The query is not DML statement: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The query is not DML statement: " + sql, JdbcStateCode.PARSING_EXCEPTION); return res; } /** {@inheritDoc} */ @Override public int executeUpdate(String sql) throws SQLException { - throw igniteSqlException("The method 'executeUpdate(String)' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { - throw igniteSqlException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int columnIndexes[]) throws SQLException { - throw igniteSqlException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, String columnNames[]) throws SQLException { - throw igniteSqlException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " + - "instance.", IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " + + "instance.", JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -257,8 +255,8 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public boolean execute(String sql) throws SQLException { - throw igniteSqlException("The method 'execute(String)' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -278,8 +276,8 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public void addBatch(String sql) throws SQLException { - throw igniteSqlException("The method 'addBatch(String)' is called on PreparedStatement instance.", - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance.", + JdbcStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -373,10 +371,10 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -515,7 +513,7 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Prepared statement is not a wrapper for " + iface.getName()); + throw new SQLException("Prepared statement is not a wrapper for " + iface.getName()); return (T)this; } @@ -536,11 +534,11 @@ private void setArgument(int paramIdx, Object val) throws SQLException { ensureNotClosed(); if (val != null && !SqlListenerUtils.isPlainType(val.getClass())) - throw igniteSqlException("Parameter type is unsupported. [cls=" + val.getClass() + ']', - IgniteQueryErrorCode.UNSUPPORTED_PARAM_TYPE); + throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']', + JdbcStateCode.INVALID_PARAMETER_VALUE); if (paramIdx < 1) - throw igniteSqlException("Parameter index is invalid: " + paramIdx); + throw new SQLException("Parameter index is invalid: " + paramIdx); if (args == null) args = new ArrayList<>(paramIdx); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index e92a78b97623e..c9b4dcf2794d3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -48,14 +48,12 @@ import java.util.List; import java.util.Map; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; import org.apache.ignite.internal.processors.query.IgniteSQLException; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; - /** * JDBC result set implementation. */ @@ -215,10 +213,10 @@ public class JdbcThinResultSet implements ResultSet { catch (IOException e) { stmt.connection().close(); - throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite.", e); + throw new SQLException("Failed to query Ignite.", e); } } @@ -268,10 +266,10 @@ void close0() throws SQLException { catch (IOException e) { stmt.connection().close(); - throw igniteSqlException("Failed to close Ignite query.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to close Ignite query.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to close Ignite query.", e); + throw new SQLException("Failed to close Ignite query.", e); } } @@ -308,12 +306,11 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()) != 0; } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to boolean: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT, - e); + throw new SQLException("Cannot convert to boolean: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to boolean: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to boolean: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -334,12 +331,11 @@ else if (cls == String.class || cls == Character.class) { return Byte.parseByte(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to byte: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, - e); + throw new SQLException("Cannot convert to byte: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to byte: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to byte: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -360,12 +356,12 @@ else if (cls == String.class || cls == Character.class) { return Short.parseShort(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to short: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + throw new SQLException("Cannot convert to short: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to short: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to short: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -386,12 +382,12 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to int: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + throw new SQLException("Cannot convert to int: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to int: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to int: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -412,12 +408,12 @@ else if (cls == String.class || cls == Character.class) { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to long: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + throw new SQLException("Cannot convert to long: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to long: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to long: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -438,12 +434,12 @@ else if (cls == String.class || cls == Character.class) { return Float.parseFloat(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to float: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + throw new SQLException("Cannot convert to float: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to float: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to float: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -464,12 +460,12 @@ else if (cls == String.class || cls == Character.class) { return Double.parseDouble(val.toString()); } catch (NumberFormatException e) { - throw igniteSqlException("Cannot convert to double: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT, + throw new SQLException("Cannot convert to double: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to double: " + val, IgniteQueryErrorCode.INVALID_NUMBER_FORMAT); + throw new SQLException("Cannot convert to double: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -511,7 +507,7 @@ else if (cls == Long.class) { else if (cls == String.class) return ((String)val).getBytes(); else - throw igniteSqlException("Cannot convert to byte[]: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to byte[]: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -528,7 +524,7 @@ else if (cls == String.class) else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class) return new Date(((java.util.Date)val).getTime()); else - throw igniteSqlException("Cannot convert to date: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to date: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -545,7 +541,7 @@ else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class) return new Time(((java.util.Date)val).getTime()); else - throw igniteSqlException("Cannot convert to time: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to time: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -562,7 +558,7 @@ else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class) return new Timestamp(((java.util.Date)val).getTime()); else - throw igniteSqlException("Cannot convert to timestamp: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to timestamp: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -581,11 +577,11 @@ else if (cls == String.class) { return new URL(val.toString()); } catch (MalformedURLException e) { - throw igniteSqlException("Cannot convert to URL: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT, e); + throw new SQLException("Cannot convert to URL: " + val, JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to URL: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to URL: " + val, JdbcStateCode.DATA_EXCEPTION); } @@ -770,7 +766,7 @@ else if (cls == String.class) { Integer order = columnOrder().get(colLb.toUpperCase()); if (order == null) - throw igniteSqlException("Column not found: " + colLb, IgniteQueryErrorCode.COLUMN_NOT_FOUND); + throw new SQLException("Column not found: " + colLb, JdbcStateCode.PARSING_EXCEPTION); assert order >= 0; @@ -811,12 +807,12 @@ else if (cls == String.class || cls == Character.class) { return (BigDecimal)decimalFormat.get().parse(val.toString()); } catch (ParseException e) { - throw igniteSqlException("Cannot convert to BigDecimal: " + val, - IgniteQueryErrorCode.INVALID_VALUE_FORMAT, e); + throw new SQLException("Cannot convert to BigDecimal: " + val, + JdbcStateCode.DATA_EXCEPTION, e); } } else - throw igniteSqlException("Cannot convert to BigDecimal: " + val, IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to BigDecimal: " + val, JdbcStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -858,28 +854,28 @@ else if (cls == String.class || cls == Character.class) { @Override public void beforeFirst() throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public void afterLast() throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean first() throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean last() throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @@ -893,21 +889,21 @@ else if (cls == String.class || cls == Character.class) { @Override public boolean absolute(int row) throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean relative(int rows) throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @Override public boolean previous() throws SQLException { ensureNotClosed(); - throw igniteSqlException("Result set is forward-only."); + throw new SQLException("Result set is forward-only."); } /** {@inheritDoc} */ @@ -930,7 +926,7 @@ else if (cls == String.class || cls == Character.class) { ensureNotClosed(); if (fetchSize <= 0) - throw igniteSqlException("Fetch size must be greater than zero."); + throw new SQLException("Fetch size must be greater than zero."); this.fetchSize = fetchSize; } @@ -1290,7 +1286,7 @@ else if (cls == String.class || cls == Character.class) { ensureNotClosed(); if (getConcurrency() == CONCUR_READ_ONLY) - throw igniteSqlException("The result set concurrency is CONCUR_READ_ONLY"); + throw new SQLException("The result set concurrency is CONCUR_READ_ONLY"); } /** {@inheritDoc} */ @@ -1783,7 +1779,7 @@ else if (cls == String.class || cls == Character.class) { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Result set is not a wrapper for " + iface.getName()); + throw new SQLException("Result set is not a wrapper for " + iface.getName()); return (T)this; } @@ -1852,8 +1848,8 @@ else if (targetCls == URL.class) if (targetCls == cls) return val; else - throw igniteSqlException("Cannot convert to " + targetCls.getName() + ": " + val, - IgniteQueryErrorCode.INVALID_VALUE_FORMAT); + throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val, + JdbcStateCode.DATA_EXCEPTION); } } @@ -1877,7 +1873,7 @@ private Object getValue(int colIdx) throws SQLException { return val; } catch (IndexOutOfBoundsException e) { - throw igniteSqlException("Invalid column index: " + colIdx, IgniteQueryErrorCode.COLUMN_NOT_FOUND, e); + throw new SQLException("Invalid column index: " + colIdx, JdbcStateCode.PARSING_EXCEPTION, e); } } @@ -1888,7 +1884,7 @@ private Object getValue(int colIdx) throws SQLException { */ private void ensureNotClosed() throws SQLException { if (closed) - throw igniteSqlException("Result set is closed.", IgniteQueryErrorCode.INVALID_RESULT_SET_STATE); + throw new SQLException("Result set is closed.", JdbcStateCode.INVALID_CURSOR_STATE); } /** @@ -1907,7 +1903,7 @@ private void ensureHasCurrentRow() throws SQLException { */ private List meta() throws SQLException { if (finished && (!isQuery || autoClose)) - throw igniteSqlException("Server cursor is already closed.", IgniteQueryErrorCode.INVALID_RESULT_SET_STATE); + throw new SQLException("Server cursor is already closed.", JdbcStateCode.INVALID_CURSOR_STATE); if (!metaInit) { try { @@ -1923,10 +1919,10 @@ private List meta() throws SQLException { catch (IOException e) { stmt.connection().close(); - throw igniteSqlException("Failed to get query metadata.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to get query metadata.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to get query metadata.", e); + throw new SQLException("Failed to get query metadata.", e); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java index a17c70ecdaf74..4c560bc07464f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java @@ -22,8 +22,6 @@ import java.util.List; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; - /** * JDBC result set metadata implementation. */ @@ -151,7 +149,7 @@ public class JdbcThinResultSetMetadata implements ResultSetMetaData { /** {@inheritDoc} */ @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Result set meta data is not a wrapper for " + iface.getName()); + throw new SQLException("Result set meta data is not a wrapper for " + iface.getName()); return (T)this; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index c78efc2e75731..816a3cea77f7d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -29,7 +29,7 @@ import java.util.List; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cache.query.SqlQuery; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; @@ -40,7 +40,6 @@ import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.FETCH_FORWARD; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; -import static org.apache.ignite.internal.jdbc2.JdbcUtils.igniteSqlException; /** * JDBC statement implementation. @@ -99,8 +98,7 @@ public class JdbcThinStatement implements Statement { ResultSet rs = getResultSet(); if (rs == null) - throw igniteSqlException("The query isn't SELECT query: " + sql, - IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The query isn't SELECT query: " + sql, JdbcStateCode.PARSING_EXCEPTION); return rs; } @@ -124,7 +122,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg alreadyRead = false; if (sql == null || sql.isEmpty()) - throw igniteSqlException("SQL query is empty."); + throw new SQLException("SQL query is empty."); try { JdbcQueryExecuteResult res = conn.io().queryExecute(stmtType, conn.getSchema(), pageSize, maxRows, @@ -141,10 +139,10 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } } @@ -155,7 +153,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg int res = getUpdateCount(); if (res == -1) - throw igniteSqlException("The query is not DML statememt: " + sql, IgniteQueryErrorCode.STMT_TYPE_MISMATCH); + throw new SQLException("The query is not DML statememt: " + sql, JdbcStateCode.PARSING_EXCEPTION); return res; } @@ -183,7 +181,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg ensureNotClosed(); if (max < 0) - throw igniteSqlException("Invalid field limit."); + throw new SQLException("Invalid field limit."); throw new SQLFeatureNotSupportedException("Field size limitation is not supported."); } @@ -200,7 +198,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg ensureNotClosed(); if (maxRows < 0) - throw igniteSqlException("Invalid max rows value."); + throw new SQLException("Invalid max rows value."); this.maxRows = maxRows; } @@ -222,7 +220,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg ensureNotClosed(); if (timeout < 0) - throw igniteSqlException("Invalid timeout value."); + throw new SQLException("Invalid timeout value."); this.timeout = timeout * 1000; } @@ -326,7 +324,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { ensureNotClosed(); if (fetchSize <= 0) - throw igniteSqlException("Fetch size must be greater than zero."); + throw new SQLException("Fetch size must be greater than zero."); this.pageSize = fetchSize; } @@ -382,7 +380,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { alreadyRead = false; if (batch == null || batch.isEmpty()) - throw igniteSqlException("Batch is empty."); + throw new SQLException("Batch is empty."); try { JdbcBatchExecuteResult res = conn.io().batchExecute(conn.getSchema(), batch); @@ -398,10 +396,10 @@ private JdbcThinResultSet lastResultSet() throws SQLException { catch (IOException e) { conn.close(); - throw igniteSqlException("Failed to query Ignite.", IgniteQueryErrorCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw igniteSqlException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); + throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); } finally { batch = null; @@ -431,7 +429,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { break; default: - throw igniteSqlException("Invalid 'current' parameter."); + throw new SQLException("Invalid 'current' parameter."); } return false; @@ -456,7 +454,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { return executeUpdate(sql); default: - throw igniteSqlException("Invalid autoGeneratedKeys value"); + throw new SQLException("Invalid autoGeneratedKeys value"); } } @@ -485,7 +483,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { return execute(sql); default: - throw igniteSqlException("Invalid autoGeneratedKeys value."); + throw new SQLException("Invalid autoGeneratedKeys value."); } } @@ -540,7 +538,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { @SuppressWarnings("unchecked") @Override public T unwrap(Class iface) throws SQLException { if (!isWrapperFor(iface)) - throw igniteSqlException("Statement is not a wrapper for " + iface.getName()); + throw new SQLException("Statement is not a wrapper for " + iface.getName()); return (T)this; } @@ -590,6 +588,6 @@ JdbcThinConnection connection() { */ protected void ensureNotClosed() throws SQLException { if (isClosed()) - throw igniteSqlException("Statement is closed."); + throw new SQLException("Statement is closed."); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java new file mode 100644 index 0000000000000..7a79de95acb34 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc2; + +import java.sql.ResultSet; + +/** + * Error codes to throw from JDBC driver (SQLSTATE codes). + */ +public final class JdbcStateCode { + /** + * No-op constructor to prevent instantiation. + */ + private JdbcStateCode() { + // No-op. + } + + /** General connection establishment error. */ + public final static String CONNECTION_ERROR = "08000"; + + /** Client has failed to open connection with specified server. */ + public final static String CLIENT_CONNECTION_FAILED = "08001"; + + /** Connection unexpectedly turned out to be in closed state. */ + public final static String CONNECTION_CLOSED = "08003"; + + /** IO error during communication. */ + public final static String CONNECTION_FAILURE = "08006"; + + /** Value can't be converted to expected type (to be used in {@link ResultSet}'s {@code getXxx()} methods. */ + public final static String DATA_EXCEPTION = "22000"; + + /** Parameter type is not supported. */ + public final static String INVALID_PARAMETER_VALUE = "22023"; + + /** Invalid result set state. */ + public final static String INVALID_CURSOR_STATE = "24000"; + + /** Invalid transaction level. */ + public final static String INVALID_TRANSACTION_LEVEL = "0700E"; + + /** Invalid data type. */ + public final static String INVALID_DATA_TYPE = "0D000"; + + /** Parsing exception. */ + public final static String PARSING_EXCEPTION = "42000"; + + /** Internal error. */ + public final static String INTERNAL_ERROR = "50000"; // Generic value for custom "50" class. +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java index a620b7d194582..eeaf5b7cca4d9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java @@ -18,13 +18,10 @@ package org.apache.ignite.internal.jdbc2; import java.net.URL; -import java.sql.SQLException; import java.sql.Time; import java.sql.Timestamp; import java.sql.Types; import java.util.Date; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.processors.query.QueryUtils; import static java.sql.Types.BIGINT; @@ -143,48 +140,4 @@ public static boolean nullable(String name, String cls) { static boolean isSqlType(Class cls) { return QueryUtils.isSqlType(cls) || cls == URL.class; } - - /** - * Create {@link SQLException} with proper {@code STATE} from given message and Ignite error code. - * @param msg error message. - * @param code error code. - * @return JDBC {@link SQLException}. - * @see IgniteQueryErrorCode - */ - public static SQLException igniteSqlException(String msg, int code) { - return new IgniteSQLException(msg, code).toJdbcException(); - } - - /** - * Create {@link SQLException} with proper {@code STATE} from given message, Ignite error code, and cause. - * @param msg error message. - * @param code error code. - * @param err cause. - * @return JDBC {@link SQLException}. - * @see IgniteQueryErrorCode - */ - public static SQLException igniteSqlException(String msg, int code, Throwable err) { - return new IgniteSQLException(msg, code, err).toJdbcException(); - } - - /** - * Create {@link SQLException} with common {@code STATE} and error code from given message. - * @param msg error message. - * @return JDBC {@link SQLException}. - * @see IgniteQueryErrorCode - */ - public static SQLException igniteSqlException(String msg) { - return new IgniteSQLException(msg).toJdbcException(); - } - - /** - * Create {@link SQLException} with common {@code STATE} and error code from given message and cause. - * @param msg error message. - * @param err cause. - * @return JDBC {@link SQLException}. - * @see IgniteQueryErrorCode - */ - public static SQLException igniteSqlException(String msg, Throwable err) { - return new IgniteSQLException(msg, err).toJdbcException(); - } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index c707c574a736f..ad88eb8be8d3c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -17,10 +17,10 @@ package org.apache.ignite.internal.processors.cache.query; -import java.sql.ResultSet; import java.sql.SQLException; import javax.cache.processor.EntryProcessor; import org.apache.ignite.IgniteCache; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; /** * Error codes for query operations. @@ -77,24 +77,9 @@ public final class IgniteQueryErrorCode { /** Required column already exists. */ public final static int COLUMN_ALREADY_EXISTS = 3009; - /** Parameter type is not supported. */ - public final static int UNSUPPORTED_PARAM_TYPE = 3010; - - /** Invalid transaction level. */ - public final static int INVALID_TRANSACTION_LEVEL = 3011; - - /** Invalid data type. */ - public final static int INVALID_DATA_TYPE = 3012; - /** Conversion failure. */ public final static int CONVERSION_FAILED = 3013; - /** Invalid number format. */ - public final static int INVALID_NUMBER_FORMAT = 3014; - - /** Value can't be converted to expected type (to be used in {@link ResultSet}'s {@code getXxx()} methods. */ - public final static int INVALID_VALUE_FORMAT = 3015; - /* 4xxx - cache related runtime errors */ /** Attempt to INSERT a key that is already in cache. */ @@ -115,23 +100,6 @@ public final class IgniteQueryErrorCode { /** Cache not found. */ public final static int CACHE_NOT_FOUND = 4006; - /* 5xxx - codes for primary use by JDBC driver. */ - - /** IO error during communication. */ - public final static int CONNECTION_FAILURE = 5001; - - /** Connect. */ - public final static int CONNECTION_CLOSED = 5002; - - /** Client failed to open connection. */ - public final static int CLIENT_CONNECTION_FAILED = 5003; - - /** General connection establishment error. */ - public final static int CONNECTION_ERROR_GENERAL = 5004; - - /** Invalid result set state. */ - public final static int INVALID_RESULT_SET_STATE = 5005; - /** */ private IgniteQueryErrorCode() { // No-op. @@ -167,37 +135,9 @@ public static String codeToSqlState(int statusCode) { case UNSUPPORTED_OPERATION: return "0A000"; // Generic value for "feature not supported" 0A class. - case CONNECTION_ERROR_GENERAL: - return "08000"; - - case CLIENT_CONNECTION_FAILED: - return "08001"; // "SQL-client unable to establish SQL-connection" - - case CONNECTION_CLOSED: - return "08003"; // "Connection does not exist" - - case CONNECTION_FAILURE: - return "08006"; // "Connection failure" - - case UNSUPPORTED_PARAM_TYPE: - return "22023"; // "Invalid parameter value" - - case INVALID_TRANSACTION_LEVEL: - return "0700E"; // "Invalid LEVEL value" - - case INVALID_DATA_TYPE: - return "0D000"; // "Invalid target type specification" - case CONVERSION_FAILED: return "0700B"; // "Data type transform function violation" - case INVALID_NUMBER_FORMAT: - case INVALID_VALUE_FORMAT: - return "22000"; // "Data exception" - - case INVALID_RESULT_SET_STATE: - return "24000"; // "Invalid cursor state" - case PARSING: case TABLE_NOT_FOUND: case TABLE_ALREADY_EXISTS: @@ -209,10 +149,10 @@ public static String codeToSqlState(int statusCode) { case UNEXPECTED_OPERATION: case UNEXPECTED_ELEMENT_TYPE: case KEY_UPDATE: - return "42000"; + return JdbcStateCode.PARSING_EXCEPTION; default: - return "50000"; // Generic value for custom "50" class. + return JdbcStateCode.INTERNAL_ERROR; } } } From 932fe5cede710547940e0acbe65afa1e24bfbc10 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Wed, 13 Sep 2017 15:44:52 +0300 Subject: [PATCH 13/43] Review fixes - 3. --- .../jdbc/JdbcErrorsAbstractSelfTest.java | 2 +- .../internal/jdbc/thin/JdbcThinTcpIo.java | 13 +-- .../ignite/internal/jdbc2/JdbcStateCode.java | 3 + .../cache/query/IgniteQueryErrorCode.java | 6 ++ .../odbc/jdbc/JdbcConnectionContext.java | 9 +- .../processors/odbc/jdbc/JdbcErrorResult.java | 88 ------------------- .../odbc/jdbc/JdbcRequestHandler.java | 87 +++++++++--------- .../processors/odbc/jdbc/JdbcResponse.java | 42 ++++----- .../processors/odbc/jdbc/JdbcResult.java | 8 -- 9 files changed, 74 insertions(+), 184 deletions(-) delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java index e942090ddf677..f600e7357a35e 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcErrorsAbstractSelfTest.java @@ -78,7 +78,7 @@ public void testIndexErrors() throws SQLException { public void testDmlErrors() throws SQLException { checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, null)", "22004"); - checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, 'zzz')", "22004"); + checkErrorState("INSERT INTO \"test\".INTEGER(_key, _val) values(1, 'zzz')", "50000"); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index 8dd2411c2a1d4..f659ae760e175 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -28,13 +28,13 @@ import org.apache.ignite.internal.binary.BinaryWriterExImpl; import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream; import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener; import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcErrorResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesRequest; @@ -356,15 +356,8 @@ public R sendRequest(JdbcRequest req, int cap) throws IOE res.readBinary(reader); - if (res.status() != SqlListenerResponse.STATUS_SUCCESS) { - if (res.response() instanceof JdbcErrorResult) { - JdbcErrorResult err = (JdbcErrorResult)res.response(); - - throw new IgniteSQLException(res.error(), err.code(), err.sqlState()); - } - - throw new IgniteCheckedException("Error server response: [req=" + req + ", resp=" + res + ']'); - } + if (res.status() != SqlListenerResponse.STATUS_SUCCESS) + throw new IgniteSQLException(res.error(), res.status(), IgniteQueryErrorCode.codeToSqlState(res.status())); return (R)res.response(); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java index 7a79de95acb34..cd7548472f00c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java @@ -51,6 +51,9 @@ private JdbcStateCode() { /** Invalid result set state. */ public final static String INVALID_CURSOR_STATE = "24000"; + /** Invalid cursor name. */ + public final static String INVALID_CURSOR_NAME = "34000"; + /** Invalid transaction level. */ public final static String INVALID_TRANSACTION_LEVEL = "0700E"; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index ad88eb8be8d3c..7d12639cba28f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -80,6 +80,9 @@ public final class IgniteQueryErrorCode { /** Conversion failure. */ public final static int CONVERSION_FAILED = 3013; + /** Invalid cursor name. */ + public final static int INVALID_CURSOR_NAME = 3014; + /* 4xxx - cache related runtime errors */ /** Attempt to INSERT a key that is already in cache. */ @@ -138,6 +141,9 @@ public static String codeToSqlState(int statusCode) { case CONVERSION_FAILED: return "0700B"; // "Data type transform function violation" + case INVALID_CURSOR_NAME: + return JdbcStateCode.INVALID_CURSOR_NAME; + case PARSING: case TABLE_NOT_FOUND: case TABLE_ALREADY_EXISTS: diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java index 5fc5ecb0b450c..bb14e6e9b7224 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java @@ -97,16 +97,11 @@ public JdbcConnectionContext(GridKernalContext ctx, GridSpinBusyLock busyLock, i boolean lazyExec = false; - boolean errorResponses = false; - - if (ver.compareTo(VER_2_1_5) >= 0) { + if (ver.compareTo(VER_2_1_5) >= 0) lazyExec = reader.readBoolean(); - errorResponses = true; - } - handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, - enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec, errorResponses); + enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec); parser = new JdbcMessageParser(ctx); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java deleted file mode 100644 index d224c4bd21279..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcErrorResult.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.processors.odbc.jdbc; - -import java.sql.SQLException; -import org.apache.ignite.binary.BinaryObjectException; -import org.apache.ignite.internal.binary.BinaryReaderExImpl; -import org.apache.ignite.internal.binary.BinaryWriterExImpl; - -/** - * Result carrying details needed to form proper {@link SQLException}. - */ -public class JdbcErrorResult extends JdbcResult { - /** - * Ignite specific error code. - */ - private int code; - - /** - * SQL state code. - */ - private String sqlState; - - /** - * Constructor. - */ - public JdbcErrorResult() { - super(JdbcResult.ERROR); - } - - /** - * Constructor. - * @param code Ignite specific error code. - * @param sqlState SQL state code. - */ - public JdbcErrorResult(int code, String sqlState) { - super(JdbcResult.ERROR); - this.code = code; - this.sqlState = sqlState; - } - - /** - * @return Ignite specific error code. - * @see SQLException#getErrorCode() () - */ - public int code() { - return code; - } - - /** - * @return SQL state code. - * @see SQLException#getSQLState() - */ - public String sqlState() { - return sqlState; - } - - /** {@inheritDoc} */ - @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException { - super.readBinary(reader); - - code = reader.readInt(); - sqlState = reader.readString(); - } - - /** {@inheritDoc} */ - @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException { - super.writeBinary(writer); - - writer.writeInt(code); - writer.writeString(sqlState); - } -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index c5f690acb998b..e9370df4b31b4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -18,7 +18,6 @@ package org.apache.ignite.internal.processors.odbc.jdbc; import java.sql.ParameterMetaData; -import java.sql.SQLException; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -37,6 +36,7 @@ import org.apache.ignite.internal.binary.BinaryWriterExImpl; import org.apache.ignite.internal.jdbc2.JdbcSqlFieldsQuery; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerRequestHandler; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; @@ -102,9 +102,6 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler { /** Automatic close of cursors. */ private final boolean autoCloseCursors; - /** */ - private final boolean errorResponses; - /** * Constructor. * @@ -117,11 +114,10 @@ public class JdbcRequestHandler implements SqlListenerRequestHandler { * @param replicatedOnly Replicated only flag. * @param autoCloseCursors Flag to automatically close server cursors. * @param lazy Lazy query execution flag. - * @param errorResponses Whether detailed {@link JdbcErrorResult} objects should be sent to client on error. */ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int maxCursors, boolean distributedJoins, boolean enforceJoinOrder, boolean collocated, boolean replicatedOnly, - boolean autoCloseCursors, boolean lazy, boolean errorResponses) { + boolean autoCloseCursors, boolean lazy) { this.ctx = ctx; this.busyLock = busyLock; this.maxCursors = maxCursors; @@ -131,7 +127,6 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int this.replicatedOnly = replicatedOnly; this.autoCloseCursors = autoCloseCursors; this.lazy = lazy; - this.errorResponses = errorResponses; log = ctx.log(getClass()); } @@ -145,7 +140,7 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int JdbcRequest req = (JdbcRequest)req0; if (!busyLock.enterBusy()) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to handle JDBC request because node is stopping."); try { @@ -184,7 +179,8 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int return getSchemas((JdbcMetaSchemasRequest)req); } - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, "Unsupported JDBC request [req=" + req + ']'); + return new JdbcResponse(IgniteQueryErrorCode.UNSUPPORTED_OPERATION, + "Unsupported JDBC request [req=" + req + ']'); } finally { busyLock.leaveBusy(); @@ -193,7 +189,7 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int /** {@inheritDoc} */ @Override public SqlListenerResponse handleException(Exception e) { - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } /** {@inheritDoc} */ @@ -221,7 +217,7 @@ private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) { int cursorCnt = qryCursors.size(); if (maxCursors > 0 && cursorCnt >= maxCursors) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, "Too many opened cursors (either close other " + + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Too many opened cursors (either close other " + "opened cursors or increase the limit through OdbcConfiguration.setMaxOpenCursors()) " + "[maximum=" + maxCursors + ", current=" + cursorCnt + ']'); @@ -258,7 +254,7 @@ private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) { qry.setLazy(lazy); if (req.pageSize() <= 0) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Invalid fetch size : [fetchSize=" + req.pageSize() + ']'); qry.setPageSize(req.pageSize()); @@ -301,7 +297,7 @@ private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) { U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -316,7 +312,7 @@ private JdbcResponse closeQuery(JdbcQueryCloseRequest req) { JdbcQueryCursor cur = qryCursors.remove(req.queryId()); if (cur == null) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, "Failed to find query cursor with ID: " + req.queryId()); cur.close(); @@ -328,7 +324,7 @@ private JdbcResponse closeQuery(JdbcQueryCloseRequest req) { U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + req.queryId() + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -343,11 +339,11 @@ private JdbcResponse fetchQuery(JdbcQueryFetchRequest req) { JdbcQueryCursor cur = qryCursors.get(req.queryId()); if (cur == null) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, "Failed to find query cursor with ID: " + req.queryId()); if (req.pageSize() <= 0) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Invalid fetch size : [fetchSize=" + req.pageSize() + ']'); cur.pageSize(req.pageSize()); @@ -365,7 +361,7 @@ private JdbcResponse fetchQuery(JdbcQueryFetchRequest req) { catch (Exception e) { U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -378,7 +374,7 @@ private JdbcResponse getQueryMeta(JdbcQueryMetadataRequest req) { JdbcQueryCursor cur = qryCursors.get(req.queryId()); if (cur == null) - return new JdbcResponse(SqlListenerResponse.STATUS_FAILED, + return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, "Failed to find query with ID: " + req.queryId()); JdbcQueryMetadataResult res = new JdbcQueryMetadataResult(req.queryId(), @@ -389,7 +385,7 @@ private JdbcResponse getQueryMeta(JdbcQueryMetadataRequest req) { catch (Exception e) { U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -440,8 +436,20 @@ private SqlListenerResponse executeBatch(JdbcBatchExecuteRequest req) { catch (Exception e) { U.error(log, "Failed to execute batch query [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(new JdbcBatchExecuteResult(Arrays.copyOf(updCnts, successQueries), - SqlListenerResponse.STATUS_FAILED, e.toString())); + int code; + + String msg; + + if (e instanceof IgniteSQLException) { + code = ((IgniteSQLException) e).statusCode(); + msg = e.getMessage(); + } + else { + code = IgniteQueryErrorCode.UNKNOWN; + msg = e.getMessage(); + } + + return new JdbcResponse(new JdbcBatchExecuteResult(Arrays.copyOf(updCnts, successQueries), code, msg)); } } @@ -475,7 +483,7 @@ private JdbcResponse getTablesMeta(JdbcMetaTablesRequest req) { catch (Exception e) { U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -517,7 +525,7 @@ private JdbcResponse getColumnsMeta(JdbcMetaColumnsRequest req) { catch (Exception e) { U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -547,7 +555,7 @@ private SqlListenerResponse getIndexesMeta(JdbcMetaIndexesRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -574,7 +582,7 @@ private SqlListenerResponse getParametersMeta(JdbcMetaParamsRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -620,7 +628,7 @@ private SqlListenerResponse getPrimaryKeys(JdbcMetaPrimaryKeysRequest req) { catch (Exception e) { U.error(log, "Failed to get parameters metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -646,7 +654,7 @@ private SqlListenerResponse getSchemas(JdbcMetaSchemasRequest req) { catch (Exception e) { U.error(log, "Failed to get schemas metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new JdbcResponse(exceptionToResult(e), SqlListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } } @@ -663,24 +671,15 @@ private static boolean matches(String str, String ptrn) { } /** - * Extract {@link SQLException} from given {@link Exception}, and form {@link JdbcErrorResult}, if possible. + * Create {@link JdbcResponse} bearing appropriate Ignite specific result code if possible + * from given {@link Exception}. * @param e Exception to convert. - * @return resulting {@link JdbcErrorResult}, or {@code null} if conversion wasn't possible. + * @return resulting {@link JdbcResponse}. */ - private JdbcErrorResult exceptionToResult(Exception e) { - if (!errorResponses) - return null; - - SQLException sqlEx = null; - - if (e instanceof SQLException) - sqlEx = (SQLException)e; - else if (e instanceof IgniteSQLException) - sqlEx = ((IgniteSQLException)e).toJdbcException(); - - if (sqlEx != null) - return new JdbcErrorResult(sqlEx.getErrorCode(), sqlEx.getSQLState()); + private JdbcResponse exceptionToResult(Exception e) { + if (e instanceof IgniteSQLException) + return new JdbcResponse(((IgniteSQLException) e).statusCode(), e.getMessage()); else - return null; + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, e.toString()); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java index 0d90b67861400..f039db769f7ab 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResponse.java @@ -46,7 +46,9 @@ public JdbcResponse() { * @param res Response result. */ public JdbcResponse(JdbcResult res) { - this(res, res instanceof JdbcErrorResult ? STATUS_FAILED : STATUS_SUCCESS, null); + super(STATUS_SUCCESS, null); + + this.res = res; } /** @@ -56,24 +58,9 @@ public JdbcResponse(JdbcResult res) { * @param err Error, {@code null} if success is {@code true}. */ public JdbcResponse(int status, @Nullable String err) { - this(null, status, err); - - assert status != STATUS_SUCCESS; - } - - /** - * Constructor for arbitrary response. - * - * @param res result. - * @param status status code. - * @param err optional error message. - */ - public JdbcResponse(JdbcResult res, int status, @Nullable String err) { super(status, err); - assert res instanceof JdbcErrorResult ^ status == STATUS_SUCCESS; - - this.res = res; + assert status != STATUS_SUCCESS; } /** @@ -92,23 +79,26 @@ public JdbcResult response() { @Override public void writeBinary(BinaryWriterExImpl writer) throws BinaryObjectException { writer.writeInt(status()); - if (status() != STATUS_SUCCESS) - writer.writeString(error()); + if (status() == STATUS_SUCCESS) { + writer.writeBoolean(res != null); - writer.writeBoolean(res != null); + if (res != null) + res.writeBinary(writer); + } + else + writer.writeString(error()); - if (res != null) - res.writeBinary(writer); } /** {@inheritDoc} */ @Override public void readBinary(BinaryReaderExImpl reader) throws BinaryObjectException { status(reader.readInt()); - if (status() != STATUS_SUCCESS) + if (status() == STATUS_SUCCESS) { + if (reader.readBoolean()) + res = JdbcResult.readResult(reader); + } + else error(reader.readString()); - - if (reader.readBoolean()) - res = JdbcResult.readResult(reader); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java index 2434e5958ab8b..202905bbc9e4d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcResult.java @@ -56,9 +56,6 @@ public class JdbcResult implements JdbcRawBinarylizable { /** Database schemas metadata result. */ static final byte META_SCHEMAS = 12; - /** Data to compose JDBC exception. */ - static final byte ERROR = 13; - /** Success status. */ private byte type; @@ -142,11 +139,6 @@ public static JdbcResult readResult(BinaryReaderExImpl reader) throws BinaryObje break; - case ERROR: - res = new JdbcErrorResult(); - - break; - default: throw new IgniteException("Unknown SQL listener request ID: [request ID=" + resId + ']'); } From 676e78e65ed177306afaf0a9af7fb43250297e5e Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Wed, 13 Sep 2017 16:27:48 +0300 Subject: [PATCH 14/43] Review fixes - 4. --- .../jdbc/thin/JdbcThinConnectionSelfTest.java | 2 +- .../jdbc/thin/JdbcThinConnection.java | 26 ++- .../jdbc/thin/JdbcThinConnectionRunnable.java | 35 ++++ .../jdbc/thin/JdbcThinDatabaseMetadata.java | 178 +++++++----------- .../jdbc/thin/JdbcThinPreparedStatement.java | 28 +-- .../internal/jdbc/thin/JdbcThinResultSet.java | 72 +++---- .../internal/jdbc/thin/JdbcThinStatement.java | 47 ++--- 7 files changed, 182 insertions(+), 206 deletions(-) create mode 100644 modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java index 9bf6282b4af76..95068c5664433 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinConnectionSelfTest.java @@ -346,7 +346,7 @@ public void testSchema() throws Exception { private static JdbcThinTcpIo io(Connection conn) throws Exception { JdbcThinConnection conn0 = conn.unwrap(JdbcThinConnection.class); - return conn0.io(); + return GridTestUtils.getFieldValue(conn0, JdbcThinConnection.class, "cliIo"); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index e15a02d691a53..453d9a4bf7d4e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.jdbc.thin; +import java.io.IOException; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; @@ -37,7 +38,9 @@ import java.util.Properties; import java.util.concurrent.Executor; import java.util.logging.Logger; +import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; @@ -634,10 +637,27 @@ private void ensureNotClosed() throws SQLException { } /** - * @return Ignite endpoint and I/O protocol. + * Run given runnable with {@link #cliIo} as param and process errors appropriately. + * @param clo Runnable. + * @param Type of value that given runnable is expected to return. + * @return Run result. + * @throws SQLException if failed. */ - public JdbcThinTcpIo io() { - return cliIo; + public T execute(JdbcThinConnectionRunnable clo) throws SQLException { + try { + return clo.run(cliIo); + } + catch (IgniteSQLException e) { + throw e.toJdbcException(); + } + catch (IOException e) { + close(); + + throw new SQLException("Failed to close Ignite query.", JdbcStateCode.CONNECTION_FAILURE, e); + } + catch (IgniteCheckedException e) { + throw new SQLException("Failed to close Ignite query.", e); + } } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java new file mode 100644 index 0000000000000..c51f188a2991a --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc.thin; + +import java.io.IOException; +import java.sql.SQLException; +import org.apache.ignite.IgniteCheckedException; + +/** + * Runnable to operate on {@link JdbcThinTcpIo} that can throw checked exceptions. + */ +interface JdbcThinConnectionRunnable { + /** + * Do run. + * @throws IOException if failed. + * @throws IgniteCheckedException if failed. + * @throws SQLException if failed. + */ + public T run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException; +} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index a5b3bc1599d87..c1e4b7853e307 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -42,7 +42,6 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcPrimaryKeyMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcTableMeta; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; import static java.sql.Connection.TRANSACTION_NONE; @@ -121,7 +120,11 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { /** {@inheritDoc} */ @Override public String getDatabaseProductVersion() throws SQLException { - return conn.io().igniteVersion().toString(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public String run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + return io.igniteVersion().toString(); + } + }); } /** {@inheritDoc} */ @@ -704,8 +707,8 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { } /** {@inheritDoc} */ - @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, - String[] tblTypes) throws SQLException { + @Override public ResultSet getTables(String catalog, final String schemaPtrn, final String tblNamePtrn, + String[] tblTypes) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -738,27 +741,18 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { if (!validCatalogPattern(catalog) || !tblTypeMatch) return new JdbcThinResultSet(Collections.>emptyList(), meta); - try { - JdbcMetaTablesResult res = conn.io().tablesMeta(schemaPtrn, tblNamePtrn); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + JdbcMetaTablesResult res = io.tablesMeta(schemaPtrn, tblNamePtrn); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (JdbcTableMeta tblMeta : res.meta()) - rows.add(tableRow(tblMeta)); + for (JdbcTableMeta tblMeta : res.meta()) + rows.add(tableRow(tblMeta)); - return new JdbcThinResultSet(rows, meta); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); - - throw new SQLException("Failed to query Ignite.", e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return new JdbcThinResultSet(rows, meta); + } + }); } /** @@ -802,8 +796,8 @@ private List tableRow(JdbcTableMeta tblMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, - String colNamePtrn) throws SQLException { + @Override public ResultSet getColumns(String catalog, final String schemaPtrn, final String tblNamePtrn, + final String colNamePtrn) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -832,27 +826,18 @@ private List tableRow(JdbcTableMeta tblMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - try { - JdbcMetaColumnsResult res = conn.io().columnsMeta(schemaPtrn, tblNamePtrn, colNamePtrn); - - List> rows = new LinkedList<>(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public JdbcThinResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + JdbcMetaColumnsResult res = io.columnsMeta(schemaPtrn, tblNamePtrn, colNamePtrn); - for (int i = 0; i < res.meta().size(); ++i) - rows.add(columnRow(res.meta().get(i), i + 1)); + List> rows = new LinkedList<>(); - return new JdbcThinResultSet(rows, meta); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); + for (int i = 0; i < res.meta().size(); ++i) + rows.add(columnRow(res.meta().get(i), i + 1)); - throw new SQLException("Failed to query Ignite.", e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return new JdbcThinResultSet(rows, meta); + } + }); } /** @@ -946,7 +931,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { } /** {@inheritDoc} */ - @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { + @Override public ResultSet getPrimaryKeys(String catalog, final String schema, final String tbl) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -961,27 +946,18 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - try { - JdbcMetaPrimaryKeysResult res = conn.io().primaryKeysMeta(schema, tbl); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + JdbcMetaPrimaryKeysResult res = io.primaryKeysMeta(schema, tbl); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (JdbcPrimaryKeyMeta pkMeta : res.meta()) - rows.addAll(primaryKeyRows(pkMeta)); + for (JdbcPrimaryKeyMeta pkMeta : res.meta()) + rows.addAll(primaryKeyRows(pkMeta)); - return new JdbcThinResultSet(rows, meta); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); - - throw new SQLException("Failed to query Ignite.", e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return new JdbcThinResultSet(rows, meta); + } + }); } /** @@ -1179,8 +1155,8 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique, - boolean approximate) throws SQLException { + @Override public ResultSet getIndexInfo(String catalog, final String schema, final String tbl, boolean unique, + boolean approximate) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -1202,27 +1178,18 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - try { - JdbcMetaIndexesResult res = conn.io().indexMeta(schema, tbl); - - List> rows = new LinkedList<>(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + JdbcMetaIndexesResult res = io.indexMeta(schema, tbl); - for (JdbcIndexMeta idxMeta : res.meta()) - rows.addAll(indexRows(idxMeta)); + List> rows = new LinkedList<>(); - return new JdbcThinResultSet(rows, meta); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); + for (JdbcIndexMeta idxMeta : res.meta()) + rows.addAll(indexRows(idxMeta)); - throw new SQLException("Failed to query Ignite.", e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return new JdbcThinResultSet(rows, meta); + } + }); } /** @@ -1418,12 +1385,20 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public int getDatabaseMajorVersion() throws SQLException { - return conn.io().igniteVersion().major(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public Byte run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + return io.igniteVersion().major(); + } + }); } /** {@inheritDoc} */ @Override public int getDatabaseMinorVersion() throws SQLException { - return conn.io().igniteVersion().minor(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public Byte run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + return io.igniteVersion().minor(); + } + }); } /** {@inheritDoc} */ @@ -1457,7 +1432,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException { + @Override public ResultSet getSchemas(String catalog, final String schemaPtrn) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -1469,33 +1444,24 @@ private List> indexRows(JdbcIndexMeta idxMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - try { - JdbcMetaSchemasResult res = conn.io().schemasMeta(schemaPtrn); - - List> rows = new LinkedList<>(); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { + JdbcMetaSchemasResult res = io.schemasMeta(schemaPtrn); - for (String schema : res.schemas()) { - List row = new ArrayList<>(2); + List> rows = new LinkedList<>(); - row.add(schema); - row.add(null); + for (String schema : res.schemas()) { + List row = new ArrayList<>(2); - rows.add(row); - } + row.add(schema); + row.add(null); - return new JdbcThinResultSet(rows, meta); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); + rows.add(row); + } - throw new SQLException("Failed to query Ignite.", e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return new JdbcThinResultSet(rows, meta); + } + }); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index 9ed6a2e92b967..b0ac2b6537554 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -46,7 +46,6 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; -import org.apache.ignite.internal.processors.query.IgniteSQLException; /** * JDBC prepared statement implementation. @@ -355,27 +354,20 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public ParameterMetaData getParameterMetaData() throws SQLException { ensureNotClosed(); - try { - if (metaData != null) - return metaData; - JdbcMetaParamsResult res = conn.io().parametersMeta(conn.getSchema(), sql); + return conn.execute(new JdbcThinConnectionRunnable() { + @Override public ParameterMetaData run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, + SQLException { + if (metaData != null) + return metaData; - metaData = new JdbcThinParameterMetadata(res.meta()); + JdbcMetaParamsResult res = io.parametersMeta(conn.getSchema(), sql); - return metaData; - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); + metaData = new JdbcThinParameterMetadata(res.meta()); - throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return metaData; + } + }); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index c9b4dcf2794d3..7da77e0635692 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -52,7 +52,6 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; -import org.apache.ignite.internal.processors.query.IgniteSQLException; /** * JDBC result set implementation. @@ -199,25 +198,18 @@ public class JdbcThinResultSet implements ResultSet { ensureNotClosed(); if ((rowsIter == null || !rowsIter.hasNext()) && !finished) { - try { - JdbcQueryFetchResult res = stmt.connection().io().queryFetch(qryId, fetchSize); + stmt.connection().execute(new JdbcThinConnectionRunnable() { + @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + JdbcQueryFetchResult res = io.queryFetch(qryId, fetchSize); - rows = res.items(); - finished = res.last(); + rows = res.items(); + finished = res.last(); - rowsIter = rows.iterator(); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - stmt.connection().close(); + rowsIter = rows.iterator(); - throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite.", e); - } + return null; + } + }); } if (rowsIter != null) { @@ -254,23 +246,16 @@ void close0() throws SQLException { if (isClosed()) return; - try { - if (!finished || (isQuery && !autoClose)) - stmt.connection().io().queryClose(qryId); + stmt.connection().execute(new JdbcThinConnectionRunnable() { + @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + if (!finished || (isQuery && !autoClose)) + io.queryClose(qryId); - closed = true; - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - stmt.connection().close(); + closed = true; - throw new SQLException("Failed to close Ignite query.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to close Ignite query.", e); - } + return null; + } + }); } /** {@inheritDoc} */ @@ -1906,24 +1891,17 @@ private List meta() throws SQLException { throw new SQLException("Server cursor is already closed.", JdbcStateCode.INVALID_CURSOR_STATE); if (!metaInit) { - try { - JdbcQueryMetadataResult res = stmt.connection().io().queryMeta(qryId); + stmt.connection().execute(new JdbcThinConnectionRunnable() { + @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + JdbcQueryMetadataResult res = io.queryMeta(qryId); - meta = res.meta(); + meta = res.meta(); - metaInit = true; - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - stmt.connection().close(); + metaInit = true; - throw new SQLException("Failed to get query metadata.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to get query metadata.", e); - } + return null; + } + }); } return meta; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 816a3cea77f7d..2e91ce1ba42af 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -35,7 +35,6 @@ import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.FETCH_FORWARD; @@ -110,7 +109,7 @@ public class JdbcThinStatement implements Statement { * * @throws SQLException Onj error. */ - protected void execute0(JdbcStatementType stmtType, String sql, List args) throws SQLException { + protected void execute0(final JdbcStatementType stmtType, final String sql, final List args) throws SQLException { ensureNotClosed(); if (rs != null) { @@ -124,26 +123,19 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg if (sql == null || sql.isEmpty()) throw new SQLException("SQL query is empty."); - try { - JdbcQueryExecuteResult res = conn.io().queryExecute(stmtType, conn.getSchema(), pageSize, maxRows, - sql, args); + conn.execute(new JdbcThinConnectionRunnable() { + @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + JdbcQueryExecuteResult res = io.queryExecute(stmtType, conn.getSchema(), pageSize, maxRows, + sql, args); - assert res != null; + assert res != null; - rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), - res.isQuery(), conn.io().autoCloseServerCursor(), res.updateCount(), closeOnCompletion); - } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); + rs = new JdbcThinResultSet(JdbcThinStatement.this, res.getQueryId(), pageSize, res.last(), res.items(), + res.isQuery(), io.autoCloseServerCursor(), res.updateCount(), closeOnCompletion); - throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } + return null; + } + }); } /** {@inheritDoc} */ @@ -383,24 +375,17 @@ private JdbcThinResultSet lastResultSet() throws SQLException { throw new SQLException("Batch is empty."); try { - JdbcBatchExecuteResult res = conn.io().batchExecute(conn.getSchema(), batch); + JdbcBatchExecuteResult res = conn.execute(new JdbcThinConnectionRunnable() { + @Override public JdbcBatchExecuteResult run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { + return io.batchExecute(conn.getSchema(), batch); + } + }); if (res.errorCode() != SqlListenerResponse.STATUS_SUCCESS) throw new BatchUpdateException(res.errorMessage(), null, res.errorCode(), res.updateCounts()); return res.updateCounts(); } - catch (IgniteSQLException e) { - throw e.toJdbcException(); - } - catch (IOException e) { - conn.close(); - - throw new SQLException("Failed to query Ignite.", JdbcStateCode.CONNECTION_FAILURE, e); - } - catch (IgniteCheckedException e) { - throw new SQLException("Failed to query Ignite [err=\"" + e.getMessage() + "\"]", e); - } finally { batch = null; } From 0c00832384a22ed0cd5c28e9ab8504558edd4e0a Mon Sep 17 00:00:00 2001 From: tledkov-gridgain Date: Wed, 13 Sep 2017 17:30:04 +0300 Subject: [PATCH 15/43] IGNITE-5620: fix tests --- .../JdbcDynamicIndexAbstractSelfTest.java | 32 ++++--------------- .../jdbc2/JdbcInsertStatementSelfTest.java | 2 +- .../JdbcThinDynamicIndexAbstractSelfTest.java | 4 +-- .../thin/JdbcThinInsertStatementSelfTest.java | 2 +- .../thin/JdbcThinNoDefaultSchemaTest.java | 2 +- .../jdbc/thin/JdbcThinResultSetSelfTest.java | 2 +- 6 files changed, 12 insertions(+), 32 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java index 7bbda6f0380d7..c6658223b043c 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java @@ -320,37 +320,17 @@ private static void assertSqlException(RunnableX r, int expCode) { try { r.run(); } - catch (SQLException ex) { - if (ex.getCause() != null) { - try { - throw ex.getCause(); - } - catch (CacheException ex1) { - if (ex1.getCause() != null) { - try { - throw ex1.getCause(); - } - catch (IgniteSQLException e) { - assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + e.statusCode() + ']', - expCode, e.statusCode()); - - return; - } - catch (Throwable t) { - fail("Unexpected exception: " + t); - } - } - } - catch (Throwable t) { - fail("Unexpected exception: " + t); - } - } + catch (SQLException e) { + assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + e.getErrorCode() + ']', + expCode, e.getErrorCode()); + + return; } catch (Exception e) { fail("Unexpected exception: " + e); } - fail(IgniteSQLException.class.getSimpleName() + " is not thrown."); + fail(SQLException.class.getSimpleName() + " is not thrown."); } /** diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java index 407d6e2c05895..2cd0c5a827c55 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java @@ -170,7 +170,7 @@ public void testDuplicateKeys() { assertNotNull(reason); - assertEquals(IgniteSQLException.class, reason.getClass()); + assertEquals(SQLException.class, reason.getClass()); assertEquals("Failed to INSERT some keys because they are already in cache [keys=[p2]]", reason.getMessage()); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java index 3f762fc60ed81..5089894ed11cc 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinDynamicIndexAbstractSelfTest.java @@ -183,7 +183,7 @@ public void testCreateIndexWithDuplicateName() throws SQLException { return null; } - }, IgniteCheckedException.class, "Index already exists: IDX"); + }, SQLException.class, "Index already exists: IDX"); } /** @@ -237,7 +237,7 @@ public void testDropMissingIndex() { return null; } - }, IgniteCheckedException.class, "Index doesn't exist: IDX"); + }, SQLException.class, "Index doesn't exist: IDX"); } /** diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java index 3b8675712ec1f..8ab5760e7c6f5 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinInsertStatementSelfTest.java @@ -177,7 +177,7 @@ public void testDuplicateKeys() { @Override public Object call() throws Exception { return stmt.execute(SQL); } - }, IgniteCheckedException.class, + }, SQLException.class, "Failed to INSERT some keys because they are already in cache [keys=[p2]]"); assertEquals(3, jcache(0).withKeepBinary().getAll(new HashSet<>(Arrays.asList("p1", "p2", "p3"))).size()); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java index 7b226e5b26e6f..65ebf9ab9148a 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinNoDefaultSchemaTest.java @@ -217,7 +217,7 @@ public void testSetSchema() throws Exception { return null; } - }, SQLException.class, "Failed to query Ignite"); + }, SQLException.class, "Failed to parse query"); conn.setSchema("cache1"); diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java index 76eb5bc12faf5..5a3c5df9f4726 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinResultSetSelfTest.java @@ -695,7 +695,7 @@ public void testObjectNotSupported() throws Exception { return null; } - }, IgniteCheckedException.class, "Custom objects are not supported"); + }, SQLException.class, "Custom objects are not supported"); } /** From 2221e8a8af1cbb42d6ccb92ec0a8ab4e4f5a381b Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Wed, 13 Sep 2017 20:01:52 +0300 Subject: [PATCH 16/43] Test fix. --- .../internal/processors/query/h2/sql/GridQueryParsingTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java index 6a78df3d6ac00..ca66bc1be0636 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java @@ -596,7 +596,7 @@ false, c("id", Value.INT), c("city", Value.STRING), c("name", Value.STRING), IgniteSQLException.class, "CREATE TABLE ... AS ... syntax is not supported"); assertParseThrows("create table Person (id int primary key)", - IgniteSQLException.class, "No cache value related columns found"); + IgniteSQLException.class, "Tables with only key related columns are not supported at the moment"); assertParseThrows("create table Person (id int primary key, age int unique) WITH \"template=cache\"", IgniteSQLException.class, "Too many constraints - only PRIMARY KEY is supported for CREATE TABLE"); From c523faa71e5dd658957de98fe8fb696280e76c25 Mon Sep 17 00:00:00 2001 From: devozerov Date: Thu, 14 Sep 2017 12:31:51 +0300 Subject: [PATCH 17/43] Cosmetics. --- .../internal/processors/query/IgniteSQLException.java | 6 ++++++ .../processors/query/h2/sql/GridSqlQueryParser.java | 2 ++ 2 files changed, 8 insertions(+) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java index e20bbe871e944..2bacc23be379b 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/query/IgniteSQLException.java @@ -43,6 +43,7 @@ public class IgniteSQLException extends IgniteException { /** * Constructor. + * * @param msg Exception message. */ public IgniteSQLException(String msg) { @@ -51,16 +52,19 @@ public IgniteSQLException(String msg) { /** * Constructor. + * * @param cause Cause to throw this exception. */ public IgniteSQLException(SQLException cause) { super(cause); + this.sqlState = cause.getSQLState(); this.statusCode = UNKNOWN; } /** * Constructor. + * * @param msg Exception message. * @param cause Cause to throw this exception. */ @@ -70,6 +74,7 @@ public IgniteSQLException(String msg, @Nullable Throwable cause) { /** * Constructor. + * * @param msg Exception message. * @param statusCode Ignite specific error code. * @param cause Cause to throw this exception. @@ -110,6 +115,7 @@ public IgniteSQLException(String msg, int statusCode, String sqlState) { */ private IgniteSQLException(String msg, int statusCode, String sqlState, @Nullable Throwable cause) { super(msg, cause); + this.sqlState = sqlState; this.statusCode = statusCode; } diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 79b7da8f9729b..8cc32c948da44 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -1027,10 +1027,12 @@ private GridSqlStatement parseAlterColumn(AlterTableAlterColumn stmt) { case CommandInterface.ALTER_TABLE_ALTER_COLUMN_SELECTIVITY: case CommandInterface.ALTER_TABLE_ALTER_COLUMN_VISIBILITY: stmtName = "ALTER COLUMN"; + break; case CommandInterface.ALTER_TABLE_DROP_COLUMN: stmtName = "DROP COLUMN"; + break; } From 5d430c2d258b0f8cf2b007376cfd34a8318d6a09 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Thu, 14 Sep 2017 23:43:28 +0300 Subject: [PATCH 18/43] IGNITE-5620 Fixes --- .../jdbc/thin/JdbcThinConnection.java | 59 +++++- .../jdbc/thin/JdbcThinConnectionRunnable.java | 35 ---- .../jdbc/thin/JdbcThinDatabaseMetadata.java | 105 ++++------- .../jdbc/thin/JdbcThinPreparedStatement.java | 18 +- .../internal/jdbc/thin/JdbcThinResultSet.java | 43 ++--- .../internal/jdbc/thin/JdbcThinStatement.java | 28 +-- .../internal/jdbc/thin/JdbcThinTcpIo.java | 173 +----------------- .../ignite/internal/jdbc2/JdbcStateCode.java | 12 ++ .../ignite/internal/jdbc2/JdbcStatement.java | 7 - .../cache/query/IgniteQueryErrorCode.java | 10 +- .../odbc/jdbc/JdbcRequestHandler.java | 6 +- .../query/h2/DmlStatementsProcessor.java | 18 +- .../query/h2/sql/GridSqlQueryParser.java | 2 +- 13 files changed, 157 insertions(+), 359 deletions(-) delete mode 100644 modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 453d9a4bf7d4e..47772b8921c44 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -40,13 +40,25 @@ import java.util.logging.Logger; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; +import org.apache.ignite.lang.IgniteProductVersion; import static java.sql.ResultSet.CLOSE_CURSORS_AT_COMMIT; import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; +import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.DYNAMIC_SIZE_MSG_CAP; +import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.MAX_BATCH_QRY_CNT; +import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_CLOSE_MSG_SIZE; +import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_FETCH_MSG_SIZE; +import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_META_MSG_SIZE; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_AUTO_CLOSE_SERVER_CURSORS; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_COLLOCATED; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_DISTRIBUTED_JOINS; @@ -637,15 +649,44 @@ private void ensureNotClosed() throws SQLException { } /** - * Run given runnable with {@link #cliIo} as param and process errors appropriately. - * @param clo Runnable. - * @param Type of value that given runnable is expected to return. - * @return Run result. - * @throws SQLException if failed. + * @return Ignite server version. */ - public T execute(JdbcThinConnectionRunnable clo) throws SQLException { + IgniteProductVersion igniteVersion() { + return cliIo.igniteVersion(); + } + + /** + * @return Auto close server cursors flag. + */ + boolean autoCloseServerCursor() { + return cliIo.autoCloseServerCursor(); + } + + /** + * Send request for execution via {@link #cliIo}. + * @param req Request. + * @return Server response. + * @throws SQLException On any error. + */ + R sendRequest(JdbcRequest req) throws SQLException { + int cap; + + if (req instanceof JdbcBatchExecuteRequest) { + int cnt = Math.min(MAX_BATCH_QRY_CNT, ((JdbcBatchExecuteRequest)req).queries().size()); + + cap = cnt * DYNAMIC_SIZE_MSG_CAP; + } + else if (req instanceof JdbcQueryCloseRequest) + cap = QUERY_CLOSE_MSG_SIZE; + else if (req instanceof JdbcQueryMetadataRequest) + cap = QUERY_META_MSG_SIZE; + else if (req instanceof JdbcQueryFetchRequest) + cap = QUERY_FETCH_MSG_SIZE; + else + cap = DYNAMIC_SIZE_MSG_CAP; + try { - return clo.run(cliIo); + return cliIo.sendRequest(req, cap); } catch (IgniteSQLException e) { throw e.toJdbcException(); @@ -653,10 +694,10 @@ public T execute(JdbcThinConnectionRunnable clo) throws SQLException { catch (IOException e) { close(); - throw new SQLException("Failed to close Ignite query.", JdbcStateCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to send Ignite JDBC request.", JdbcStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { - throw new SQLException("Failed to close Ignite query.", e); + throw new SQLException("Failed to send Ignite JDBC request.", e); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java deleted file mode 100644 index c51f188a2991a..0000000000000 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnectionRunnable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.jdbc.thin; - -import java.io.IOException; -import java.sql.SQLException; -import org.apache.ignite.IgniteCheckedException; - -/** - * Runnable to operate on {@link JdbcThinTcpIo} that can throw checked exceptions. - */ -interface JdbcThinConnectionRunnable { - /** - * Do run. - * @throws IOException if failed. - * @throws IgniteCheckedException if failed. - * @throws SQLException if failed. - */ - public T run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException; -} diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index c1e4b7853e307..08a2a72613c3c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.jdbc.thin; -import java.io.IOException; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; @@ -29,16 +28,20 @@ import java.util.Collections; import java.util.LinkedList; import java.util.List; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.IgniteVersionUtils; import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.jdbc2.JdbcUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcPrimaryKeyMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcTableMeta; @@ -120,11 +123,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { /** {@inheritDoc} */ @Override public String getDatabaseProductVersion() throws SQLException { - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public String run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - return io.igniteVersion().toString(); - } - }); + return conn.igniteVersion().toString(); } /** {@inheritDoc} */ @@ -741,18 +740,14 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { if (!validCatalogPattern(catalog) || !tblTypeMatch) return new JdbcThinResultSet(Collections.>emptyList(), meta); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - JdbcMetaTablesResult res = io.tablesMeta(schemaPtrn, tblNamePtrn); + JdbcMetaTablesResult res = conn.sendRequest(new JdbcMetaTablesRequest(schemaPtrn, tblNamePtrn)); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (JdbcTableMeta tblMeta : res.meta()) - rows.add(tableRow(tblMeta)); + for (JdbcTableMeta tblMeta : res.meta()) + rows.add(tableRow(tblMeta)); - return new JdbcThinResultSet(rows, meta); - } - }); + return new JdbcThinResultSet(rows, meta); } /** @@ -826,18 +821,14 @@ private List tableRow(JdbcTableMeta tblMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public JdbcThinResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - JdbcMetaColumnsResult res = io.columnsMeta(schemaPtrn, tblNamePtrn, colNamePtrn); + JdbcMetaColumnsResult res = conn.sendRequest(new JdbcMetaColumnsRequest(schemaPtrn, tblNamePtrn, colNamePtrn)); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (int i = 0; i < res.meta().size(); ++i) - rows.add(columnRow(res.meta().get(i), i + 1)); + for (int i = 0; i < res.meta().size(); ++i) + rows.add(columnRow(res.meta().get(i), i + 1)); - return new JdbcThinResultSet(rows, meta); - } - }); + return new JdbcThinResultSet(rows, meta); } /** @@ -931,7 +922,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { } /** {@inheritDoc} */ - @Override public ResultSet getPrimaryKeys(String catalog, final String schema, final String tbl) throws SQLException { + @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); @@ -946,18 +937,14 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - JdbcMetaPrimaryKeysResult res = io.primaryKeysMeta(schema, tbl); + JdbcMetaPrimaryKeysResult res = conn.sendRequest(new JdbcMetaPrimaryKeysRequest(schema, tbl)); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (JdbcPrimaryKeyMeta pkMeta : res.meta()) - rows.addAll(primaryKeyRows(pkMeta)); + for (JdbcPrimaryKeyMeta pkMeta : res.meta()) + rows.addAll(primaryKeyRows(pkMeta)); - return new JdbcThinResultSet(rows, meta); - } - }); + return new JdbcThinResultSet(rows, meta); } /** @@ -1178,18 +1165,14 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - JdbcMetaIndexesResult res = io.indexMeta(schema, tbl); + JdbcMetaIndexesResult res = conn.sendRequest(new JdbcMetaIndexesRequest(schema, tbl)); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (JdbcIndexMeta idxMeta : res.meta()) - rows.addAll(indexRows(idxMeta)); + for (JdbcIndexMeta idxMeta : res.meta()) + rows.addAll(indexRows(idxMeta)); - return new JdbcThinResultSet(rows, meta); - } - }); + return new JdbcThinResultSet(rows, meta); } /** @@ -1385,20 +1368,12 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public int getDatabaseMajorVersion() throws SQLException { - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public Byte run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - return io.igniteVersion().major(); - } - }); + return conn.igniteVersion().major(); } /** {@inheritDoc} */ @Override public int getDatabaseMinorVersion() throws SQLException { - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public Byte run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - return io.igniteVersion().minor(); - } - }); + return conn.igniteVersion().minor(); } /** {@inheritDoc} */ @@ -1444,24 +1419,20 @@ private List> indexRows(JdbcIndexMeta idxMeta) { if (!validCatalogPattern(catalog)) return new JdbcThinResultSet(Collections.>emptyList(), meta); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public ResultSet run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException { - JdbcMetaSchemasResult res = io.schemasMeta(schemaPtrn); + JdbcMetaSchemasResult res = conn.sendRequest(new JdbcMetaSchemasRequest(schemaPtrn)); - List> rows = new LinkedList<>(); + List> rows = new LinkedList<>(); - for (String schema : res.schemas()) { - List row = new ArrayList<>(2); + for (String schema : res.schemas()) { + List row = new ArrayList<>(2); - row.add(schema); - row.add(null); + row.add(schema); + row.add(null); - rows.add(row); - } + rows.add(row); + } - return new JdbcThinResultSet(rows, meta); - } - }); + return new JdbcThinResultSet(rows, meta); } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index b0ac2b6537554..f265f8bdef932 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.jdbc.thin; -import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; @@ -40,9 +39,9 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; @@ -355,19 +354,14 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio @Override public ParameterMetaData getParameterMetaData() throws SQLException { ensureNotClosed(); - return conn.execute(new JdbcThinConnectionRunnable() { - @Override public ParameterMetaData run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, - SQLException { - if (metaData != null) - return metaData; + if (metaData != null) + return metaData; - JdbcMetaParamsResult res = io.parametersMeta(conn.getSchema(), sql); + JdbcMetaParamsResult res = conn.sendRequest(new JdbcMetaParamsRequest(conn.getSchema(), sql)); - metaData = new JdbcThinParameterMetadata(res.meta()); + metaData = new JdbcThinParameterMetadata(res.meta()); - return metaData; - } - }); + return metaData; } /** {@inheritDoc} */ diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index 7da77e0635692..b8b9c0e949996 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.jdbc.thin; -import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.math.BigDecimal; @@ -47,10 +46,12 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; /** @@ -198,18 +199,12 @@ public class JdbcThinResultSet implements ResultSet { ensureNotClosed(); if ((rowsIter == null || !rowsIter.hasNext()) && !finished) { - stmt.connection().execute(new JdbcThinConnectionRunnable() { - @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - JdbcQueryFetchResult res = io.queryFetch(qryId, fetchSize); + JdbcQueryFetchResult res = stmt.conn.sendRequest(new JdbcQueryFetchRequest(qryId, fetchSize)); - rows = res.items(); - finished = res.last(); + rows = res.items(); + finished = res.last(); - rowsIter = rows.iterator(); - - return null; - } - }); + rowsIter = rows.iterator(); } if (rowsIter != null) { @@ -246,16 +241,10 @@ void close0() throws SQLException { if (isClosed()) return; - stmt.connection().execute(new JdbcThinConnectionRunnable() { - @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - if (!finished || (isQuery && !autoClose)) - io.queryClose(qryId); - - closed = true; + if (!finished || (isQuery && !autoClose)) + stmt.conn.sendRequest(new JdbcQueryCloseRequest(qryId)); - return null; - } - }); + closed = true; } /** {@inheritDoc} */ @@ -1891,17 +1880,11 @@ private List meta() throws SQLException { throw new SQLException("Server cursor is already closed.", JdbcStateCode.INVALID_CURSOR_STATE); if (!metaInit) { - stmt.connection().execute(new JdbcThinConnectionRunnable() { - @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - JdbcQueryMetadataResult res = io.queryMeta(qryId); - - meta = res.meta(); + JdbcQueryMetadataResult res = stmt.conn.sendRequest(new JdbcQueryMetadataRequest(qryId)); - metaInit = true; + meta = res.meta(); - return null; - } - }); + metaInit = true; } return meta; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 2e91ce1ba42af..f98d9ae63fec9 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.jdbc.thin; -import java.io.IOException; import java.sql.BatchUpdateException; import java.sql.Connection; import java.sql.ResultSet; @@ -27,12 +26,13 @@ import java.sql.Statement; import java.util.ArrayList; import java.util.List; -import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.cache.query.SqlQuery; import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; @@ -109,7 +109,7 @@ public class JdbcThinStatement implements Statement { * * @throws SQLException Onj error. */ - protected void execute0(final JdbcStatementType stmtType, final String sql, final List args) throws SQLException { + protected void execute0(JdbcStatementType stmtType, String sql, List args) throws SQLException { ensureNotClosed(); if (rs != null) { @@ -123,19 +123,13 @@ protected void execute0(final JdbcStatementType stmtType, final String sql, fina if (sql == null || sql.isEmpty()) throw new SQLException("SQL query is empty."); - conn.execute(new JdbcThinConnectionRunnable() { - @Override public Void run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - JdbcQueryExecuteResult res = io.queryExecute(stmtType, conn.getSchema(), pageSize, maxRows, - sql, args); + JdbcQueryExecuteResult res = conn.sendRequest(new JdbcQueryExecuteRequest(stmtType, conn.getSchema(), pageSize, + maxRows, sql, args == null ? null : args.toArray(new Object[args.size()]))); - assert res != null; + assert res != null; - rs = new JdbcThinResultSet(JdbcThinStatement.this, res.getQueryId(), pageSize, res.last(), res.items(), - res.isQuery(), io.autoCloseServerCursor(), res.updateCount(), closeOnCompletion); - - return null; - } - }); + rs = new JdbcThinResultSet(JdbcThinStatement.this, res.getQueryId(), pageSize, res.last(), res.items(), + res.isQuery(), conn.autoCloseServerCursor(), res.updateCount(), closeOnCompletion); } /** {@inheritDoc} */ @@ -375,11 +369,7 @@ private JdbcThinResultSet lastResultSet() throws SQLException { throw new SQLException("Batch is empty."); try { - JdbcBatchExecuteResult res = conn.execute(new JdbcThinConnectionRunnable() { - @Override public JdbcBatchExecuteResult run(JdbcThinTcpIo io) throws IgniteCheckedException, IOException, SQLException { - return io.batchExecute(conn.getSchema(), batch); - } - }); + JdbcBatchExecuteResult res = conn.sendRequest(new JdbcBatchExecuteRequest(conn.getSchema(), batch)); if (res.errorCode() != SqlListenerResponse.STATUS_SUCCESS) throw new BatchUpdateException(res.errorMessage(), null, res.errorCode(), res.updateCounts()); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index f659ae760e175..8ae3e650d448c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -22,7 +22,6 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; -import java.util.List; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.binary.BinaryReaderExImpl; import org.apache.ignite.internal.binary.BinaryWriterExImpl; @@ -33,32 +32,9 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaColumnsResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaIndexesResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaPrimaryKeysResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaSchemasResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaTablesResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQuery; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcStatementType; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint; import org.apache.ignite.internal.util.typedef.internal.U; @@ -78,19 +54,19 @@ public class JdbcThinTcpIo { private static final int HANDSHAKE_MSG_SIZE = 13; /** Initial output for query message. */ - private static final int DYNAMIC_SIZE_MSG_CAP = 256; + static final int DYNAMIC_SIZE_MSG_CAP = 256; /** Maximum batch query count. */ - private static final int MAX_BATCH_QRY_CNT = 32; + static final int MAX_BATCH_QRY_CNT = 32; /** Initial output for query fetch message. */ - private static final int QUERY_FETCH_MSG_SIZE = 13; + static final int QUERY_FETCH_MSG_SIZE = 13; /** Initial output for query fetch message. */ - private static final int QUERY_META_MSG_SIZE = 9; + static final int QUERY_META_MSG_SIZE = 9; /** Initial output for query close message. */ - private static final int QUERY_CLOSE_MSG_SIZE = 9; + static final int QUERY_CLOSE_MSG_SIZE = 9; /** Host. */ private final String host; @@ -317,33 +293,15 @@ public void handshake_2_1_0() throws IOException, IgniteCheckedException { } } - /** - * @param stmtType Expected statement type. - * @param cache Cache name. - * @param fetchSize Fetch size. - * @param maxRows Max rows. - * @param sql SQL statement. - * @param args Query parameters. - * @return Execute query results. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcQueryExecuteResult queryExecute(JdbcStatementType stmtType, String cache, int fetchSize, int maxRows, - String sql, List args) - throws IOException, IgniteCheckedException { - return sendRequest(new JdbcQueryExecuteRequest(stmtType, cache, fetchSize, maxRows, sql, - args == null ? null : args.toArray(new Object[args.size()])), DYNAMIC_SIZE_MSG_CAP); - } - /** * @param req Request. - * @param cap Initial ouput stream capacity. + * @param cap Initial output stream capacity. * @return Server response. * @throws IOException On IO error. * @throws IgniteCheckedException On error. */ @SuppressWarnings("unchecked") - public R sendRequest(JdbcRequest req, int cap) throws IOException, IgniteCheckedException { + R sendRequest(JdbcRequest req, int cap) throws IOException, IgniteCheckedException { BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null); req.writeBinary(writer); @@ -362,121 +320,6 @@ public R sendRequest(JdbcRequest req, int cap) throws IOE return (R)res.response(); } - /** - * @param qryId Query ID. - * @param pageSize pageSize. - * @return Fetch results. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcQueryFetchResult queryFetch(Long qryId, int pageSize) - throws IOException, IgniteCheckedException { - return sendRequest(new JdbcQueryFetchRequest(qryId, pageSize), QUERY_FETCH_MSG_SIZE); - } - - - /** - * @param qryId Query ID. - * @return Fetch results. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcQueryMetadataResult queryMeta(Long qryId) - throws IOException, IgniteCheckedException { - return sendRequest(new JdbcQueryMetadataRequest(qryId), QUERY_META_MSG_SIZE); - } - - /** - * @param qryId Query ID. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public void queryClose(long qryId) throws IOException, IgniteCheckedException { - sendRequest(new JdbcQueryCloseRequest(qryId), QUERY_CLOSE_MSG_SIZE); - } - - /** - * @param schemaName Schema. - * @param batch Batch queries. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcBatchExecuteResult batchExecute(String schemaName, List batch) - throws IOException, IgniteCheckedException { - int cnt = Math.min(MAX_BATCH_QRY_CNT, batch.size()); - - return sendRequest(new JdbcBatchExecuteRequest(schemaName, batch), DYNAMIC_SIZE_MSG_CAP * cnt); - } - - /** - * @param schemaPtrn Schema name pattern. - * @param tablePtrn Table name pattern. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaTablesResult tablesMeta(String schemaPtrn, String tablePtrn) - throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaTablesRequest(schemaPtrn, tablePtrn), DYNAMIC_SIZE_MSG_CAP); - } - - /** - * @param schemaPtrn Schema name pattern. - * @param tablePtrn Table name pattern. - * @param columnPtrn Column name pattern. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaColumnsResult columnsMeta(String schemaPtrn, String tablePtrn, String columnPtrn) - throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaColumnsRequest(schemaPtrn, tablePtrn, columnPtrn), DYNAMIC_SIZE_MSG_CAP); - } - - /** - * @param schemaPtrn Schema name pattern. - * @param tablePtrn Table name pattern. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaIndexesResult indexMeta(String schemaPtrn, String tablePtrn) throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaIndexesRequest(schemaPtrn, tablePtrn), DYNAMIC_SIZE_MSG_CAP); - } - - /** - * @param schemaPtrn Schema name pattern. - * @param sql SQL query. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaParamsResult parametersMeta(String schemaPtrn, String sql) throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaParamsRequest(schemaPtrn, sql), DYNAMIC_SIZE_MSG_CAP); - } - - /** - * @param schemaPtrn Schema name pattern. - * @param tablePtrn Table name pattern. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaPrimaryKeysResult primaryKeysMeta(String schemaPtrn, String tablePtrn) throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaPrimaryKeysRequest(schemaPtrn, tablePtrn), DYNAMIC_SIZE_MSG_CAP); - } - - /** - * @param schemaPtrn Schema name pattern. - * @return Result. - * @throws IOException On error. - * @throws IgniteCheckedException On error. - */ - public JdbcMetaSchemasResult schemasMeta(String schemaPtrn) throws IOException, IgniteCheckedException { - return sendRequest(new JdbcMetaSchemasRequest(schemaPtrn), DYNAMIC_SIZE_MSG_CAP); - } - /** * @param req JDBC request bytes. * @throws IOException On error. @@ -605,7 +448,7 @@ public boolean tcpNoDelay() { } /** - * @return Ignnite server version. + * @return Ignite server version. */ IgniteProductVersion igniteVersion() { return igniteVer; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java index cd7548472f00c..7cec70ccee41e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java @@ -45,18 +45,30 @@ private JdbcStateCode() { /** Value can't be converted to expected type (to be used in {@link ResultSet}'s {@code getXxx()} methods. */ public final static String DATA_EXCEPTION = "22000"; + /** Null value occurred where it wasn't expected to. */ + public final static String NULL_VALUE = "22004"; + /** Parameter type is not supported. */ public final static String INVALID_PARAMETER_VALUE = "22023"; + /** Data integrity constraint violation. */ + public final static String CONSTRAINT_VIOLATION = "23000"; + /** Invalid result set state. */ public final static String INVALID_CURSOR_STATE = "24000"; /** Invalid cursor name. */ public final static String INVALID_CURSOR_NAME = "34000"; + /** Conversion failure. */ + public final static String CONVERSION_FAILED = "0700B"; + /** Invalid transaction level. */ public final static String INVALID_TRANSACTION_LEVEL = "0700E"; + /** Requested operation is not supported. */ + public final static String UNSUPPORTED_OPERATION = "0A000"; + /** Invalid data type. */ public final static String INVALID_DATA_TYPE = "0D000"; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java index 984aadfa6fb51..4e05db4ee3f4d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStatement.java @@ -31,7 +31,6 @@ import java.util.Map; import java.util.Set; import java.util.UUID; -import javax.cache.CacheException; import org.apache.ignite.Ignite; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; @@ -362,12 +361,6 @@ sql, null, loc, getArgs(), fetchSize, uuid, conn.isLocalQuery(), conn.isCollocat catch (IgniteSQLException e) { throw e.toJdbcException(); } - catch (CacheException e) { - if (e.getCause() instanceof IgniteSQLException) - throw ((IgniteSQLException) e.getCause()).toJdbcException(); - else - throw new SQLException("Failed to query Ignite.", e); - } catch (Exception e) { throw new SQLException("Failed to query Ignite.", e); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index 7d12639cba28f..16353b84e9932 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -116,7 +116,7 @@ private IgniteQueryErrorCode() { * @return {@link SQLException} with given details. */ public static SQLException createJdbcSqlException(String msg, int code) { - return new SQLException(msg, codeToSqlState(code), code); + return new SQLException(msg, codeToSqlState(code)); } /** @@ -129,17 +129,17 @@ public static SQLException createJdbcSqlException(String msg, int code) { public static String codeToSqlState(int statusCode) { switch (statusCode) { case DUPLICATE_KEY: - return "23000"; // Generic value for "integrity constraint violation" 23 class. + return JdbcStateCode.CONSTRAINT_VIOLATION; case NULL_KEY: case NULL_VALUE: - return "22004"; // "Null value not allowed". + return JdbcStateCode.NULL_VALUE; case UNSUPPORTED_OPERATION: - return "0A000"; // Generic value for "feature not supported" 0A class. + return JdbcStateCode.UNSUPPORTED_OPERATION; case CONVERSION_FAILED: - return "0700B"; // "Data type transform function violation" + return JdbcStateCode.CONVERSION_FAILED; case INVALID_CURSOR_NAME: return JdbcStateCode.INVALID_CURSOR_NAME; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index 32a203fad0e11..249f505f3a459 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -330,7 +330,7 @@ private JdbcResponse closeQuery(JdbcQueryCloseRequest req) { JdbcQueryCursor cur = qryCursors.remove(req.queryId()); if (cur == null) - return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to find query cursor with ID: " + req.queryId()); cur.close(); @@ -357,7 +357,7 @@ private JdbcResponse fetchQuery(JdbcQueryFetchRequest req) { JdbcQueryCursor cur = qryCursors.get(req.queryId()); if (cur == null) - return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to find query cursor with ID: " + req.queryId()); if (req.pageSize() <= 0) @@ -392,7 +392,7 @@ private JdbcResponse getQueryMeta(JdbcQueryMetadataRequest req) { JdbcQueryCursor cur = qryCursors.get(req.queryId()); if (cur == null) - return new JdbcResponse(IgniteQueryErrorCode.INVALID_CURSOR_NAME, + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to find query with ID: " + req.queryId()); JdbcQueryMetadataResult res = new JdbcQueryMetadataResult(req.queryId(), diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java index 90f547375aef8..613a284ba167c 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java @@ -49,6 +49,7 @@ import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.internal.GridKernalContext; +import org.apache.ignite.internal.jdbc2.JdbcStateCode; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheAdapter; @@ -687,11 +688,13 @@ private static Object convert(Object val, GridH2RowDescriptor desc, Class exp return LocalDateTimeUtils.valueToLocalTime(ValueTime.get((Time) val)); } - // We have to convert arrays of reference types manually - see https://issues.apache.org/jira/browse/IGNITE-4327 + // We have to convert arrays of reference types manually - + // see https://issues.apache.org/jira/browse/IGNITE-4327 // Still, we only can convert from Object[] to something more precise. if (type == Value.ARRAY && currCls != expCls) { if (currCls != Object[].class) - throw new IgniteCheckedException("Unexpected array type - only conversion from Object[] is assumed"); + throw new IgniteCheckedException("Unexpected array type - only conversion from Object[] " + + "is assumed"); // Why would otherwise type be Value.ARRAY? assert expCls.isArray(); @@ -708,7 +711,8 @@ private static Object convert(Object val, GridH2RowDescriptor desc, Class exp return H2Utils.convert(val, desc, type); } catch (Exception e) { - throw new IgniteSQLException("Value conversion failed.", IgniteQueryErrorCode.CONVERSION_FAILED, e); + throw new IgniteSQLException("Value conversion failed [origCls=" + currCls.getName() + ", targetCls=" + + expCls +']', IgniteQueryErrorCode.CONVERSION_FAILED, e); } } @@ -844,7 +848,7 @@ private long doInsert(UpdatePlan plan, Iterable> cursor, int pageSize) t String msg = "Failed to INSERT some keys because they are already in cache " + "[keys=" + sender.failedKeys() + ']'; - SQLException dupEx = new SQLException(msg, null, IgniteQueryErrorCode.DUPLICATE_KEY); + SQLException dupEx = new SQLException(msg, JdbcStateCode.CONSTRAINT_VIOLATION); if (resEx == null) resEx = dupEx; @@ -977,7 +981,8 @@ private InsertEntryProcessor(Object val) { } /** {@inheritDoc} */ - @Override public Boolean process(MutableEntry entry, Object... arguments) throws EntryProcessorException { + @Override public Boolean process(MutableEntry entry, Object... arguments) + throws EntryProcessorException { if (entry.exists()) return false; @@ -1005,7 +1010,8 @@ private ModifyingEntryProcessor(Object val, IgniteInClosure entry, Object... arguments) throws EntryProcessorException { + @Override public Boolean process(MutableEntry entry, Object... arguments) + throws EntryProcessorException { if (!entry.exists()) return null; // Someone got ahead of us and removed this entry, let's skip it. diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 8cc32c948da44..530c1ae3935c5 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -1037,7 +1037,7 @@ private GridSqlStatement parseAlterColumn(AlterTableAlterColumn stmt) { } if (stmtName == null) { - throw new IgniteSQLException("Unsupported operation code: " + stmt.getType(), + throw new IgniteSQLException("Unsupported ALTER TABLE operation: " + stmt.getSQL(), IgniteQueryErrorCode.UNSUPPORTED_OPERATION); } else { From 60ef82631adc289e2024ae72a71a9c0c80f59b92 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:23:01 +0300 Subject: [PATCH 19/43] Cosmetics. --- .../internal/processors/query/h2/DmlStatementsProcessor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java index 613a284ba167c..f099b997ab382 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java @@ -711,8 +711,8 @@ private static Object convert(Object val, GridH2RowDescriptor desc, Class exp return H2Utils.convert(val, desc, type); } catch (Exception e) { - throw new IgniteSQLException("Value conversion failed [origCls=" + currCls.getName() + ", targetCls=" + - expCls +']', IgniteQueryErrorCode.CONVERSION_FAILED, e); + throw new IgniteSQLException("Value conversion failed [from=" + currCls.getName() + ", to=" + + expCls.getName() +']', IgniteQueryErrorCode.CONVERSION_FAILED, e); } } From ac7745020f9ebc9e19ebeb31cebab32a77220e86 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:25:30 +0300 Subject: [PATCH 20/43] Cosmetics. --- .../processors/query/h2/sql/GridSqlQueryParser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 530c1ae3935c5..6e27f9b08f458 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -941,7 +941,7 @@ private GridSqlCreateTable parseCreateTable(CreateTable createTbl) { int valColsNum = cols.size() - pkCols.size(); if (valColsNum == 0) - throw new IgniteSQLException("Tables with only key related columns are not supported at the moment", + throw new IgniteSQLException("Table must have at least one non PRIMARY KEY columnn.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION); res.columns(cols); @@ -1037,11 +1037,11 @@ private GridSqlStatement parseAlterColumn(AlterTableAlterColumn stmt) { } if (stmtName == null) { - throw new IgniteSQLException("Unsupported ALTER TABLE operation: " + stmt.getSQL(), + throw new IgniteSQLException("Unsupported operation: " + stmt.getSQL(), IgniteQueryErrorCode.UNSUPPORTED_OPERATION); } else { - throw new IgniteSQLException("Unsupported ALTER TABLE operation: " + stmtName, + throw new IgniteSQLException(stmtName + " is not supported", IgniteQueryErrorCode.UNSUPPORTED_OPERATION); } } From 852cf4a999bede9d71cc53dd93bc208b3bc0ca76 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:28:51 +0300 Subject: [PATCH 21/43] Removed INVALID_CURSOR_NAME. --- .../org/apache/ignite/internal/jdbc2/JdbcStateCode.java | 3 --- .../processors/cache/query/IgniteQueryErrorCode.java | 6 ------ 2 files changed, 9 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java index 7cec70ccee41e..0d0e73c361e0a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java @@ -57,9 +57,6 @@ private JdbcStateCode() { /** Invalid result set state. */ public final static String INVALID_CURSOR_STATE = "24000"; - /** Invalid cursor name. */ - public final static String INVALID_CURSOR_NAME = "34000"; - /** Conversion failure. */ public final static String CONVERSION_FAILED = "0700B"; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index 16353b84e9932..dafb8db5ed066 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -80,9 +80,6 @@ public final class IgniteQueryErrorCode { /** Conversion failure. */ public final static int CONVERSION_FAILED = 3013; - /** Invalid cursor name. */ - public final static int INVALID_CURSOR_NAME = 3014; - /* 4xxx - cache related runtime errors */ /** Attempt to INSERT a key that is already in cache. */ @@ -141,9 +138,6 @@ public static String codeToSqlState(int statusCode) { case CONVERSION_FAILED: return JdbcStateCode.CONVERSION_FAILED; - case INVALID_CURSOR_NAME: - return JdbcStateCode.INVALID_CURSOR_NAME; - case PARSING: case TABLE_NOT_FOUND: case TABLE_ALREADY_EXISTS: From 91f6bc4302c8c4b3132aefe08487ad17c2d1f347 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:31:52 +0300 Subject: [PATCH 22/43] Renamed JdbcStateCode -> SqlStateCode. --- .../jdbc/thin/JdbcThinConnection.java | 26 ++++----- .../jdbc/thin/JdbcThinDatabaseMetadata.java | 12 ++-- .../jdbc/thin/JdbcThinPreparedStatement.java | 22 ++++---- .../internal/jdbc/thin/JdbcThinResultSet.java | 56 +++++++++---------- .../internal/jdbc/thin/JdbcThinStatement.java | 6 +- .../cache/query/IgniteQueryErrorCode.java | 14 ++--- .../odbc/SqlStateCode.java} | 8 +-- .../query/h2/DmlStatementsProcessor.java | 4 +- 8 files changed, 74 insertions(+), 74 deletions(-) rename modules/core/src/main/java/org/apache/ignite/internal/{jdbc2/JdbcStateCode.java => processors/odbc/SqlStateCode.java} (94%) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 47772b8921c44..f562452e8b53a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -39,7 +39,7 @@ import java.util.concurrent.Executor; import java.util.logging.Logger; import org.apache.ignite.IgniteCheckedException; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; @@ -155,7 +155,7 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ cliIo.close(); throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', - JdbcStateCode.CLIENT_CONNECTION_FAILED, e); + SqlStateCode.CLIENT_CONNECTION_FAILED, e); } } @@ -364,7 +364,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, break; default: - throw new SQLException("Invalid transaction isolation level.", JdbcStateCode.INVALID_TRANSACTION_LEVEL); + throw new SQLException("Invalid transaction isolation level.", SqlStateCode.INVALID_TRANSACTION_LEVEL); } txIsolation = level; @@ -567,7 +567,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null.", JdbcStateCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null.", SqlStateCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -577,7 +577,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null.", JdbcStateCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null.", SqlStateCode.INVALID_DATA_TYPE); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -645,7 +645,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, */ private void ensureNotClosed() throws SQLException { if (closed) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); } /** @@ -694,7 +694,7 @@ else if (req instanceof JdbcQueryFetchRequest) catch (IOException e) { close(); - throw new SQLException("Failed to send Ignite JDBC request.", JdbcStateCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to send Ignite JDBC request.", SqlStateCode.CONNECTION_FAILURE, e); } catch (IgniteCheckedException e) { throw new SQLException("Failed to send Ignite JDBC request.", e); @@ -715,7 +715,7 @@ private static String extractHost(Properties props) throws SQLException { host = host.trim(); if (F.isEmpty(host)) - throw new SQLException("Host name is empty.", JdbcStateCode.CONNECTION_ERROR); + throw new SQLException("Host name is empty.", SqlStateCode.CONNECTION_ERROR); return host; } @@ -739,10 +739,10 @@ private static int extractPort(Properties props) throws SQLException { port = Integer.parseInt(portStr); if (port <= 0 || port > 0xFFFF) - throw new SQLException("Invalid port: " + portStr, JdbcStateCode.CONNECTION_ERROR); + throw new SQLException("Invalid port: " + portStr, SqlStateCode.CONNECTION_ERROR); } catch (NumberFormatException e) { - throw new SQLException("Invalid port: " + portStr, JdbcStateCode.CONNECTION_ERROR); + throw new SQLException("Invalid port: " + portStr, SqlStateCode.CONNECTION_ERROR); } return port; @@ -769,7 +769,7 @@ else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal)) return false; else throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', JdbcStateCode.CONNECTION_ERROR); + ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); } /** @@ -786,7 +786,7 @@ private static int extractIntNonNegative(Properties props, String propName, int if (res < 0) throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + res + ']', JdbcStateCode.CONNECTION_ERROR); + ", value=" + res + ']', SqlStateCode.CONNECTION_ERROR); return res; } @@ -811,7 +811,7 @@ private static int extractInt(Properties props, String propName, int dfltVal) th } catch (NumberFormatException e) { throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', JdbcStateCode.CONNECTION_ERROR); + ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index 08a2a72613c3c..d095ef5faa940 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -29,7 +29,7 @@ import java.util.LinkedList; import java.util.List; import org.apache.ignite.internal.IgniteVersionUtils; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.jdbc2.JdbcUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta; @@ -709,7 +709,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { @Override public ResultSet getTables(String catalog, final String schemaPtrn, final String tblNamePtrn, String[] tblTypes) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -794,7 +794,7 @@ private List tableRow(JdbcTableMeta tblMeta) { @Override public ResultSet getColumns(String catalog, final String schemaPtrn, final String tblNamePtrn, final String colNamePtrn) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -924,7 +924,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { /** {@inheritDoc} */ @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1145,7 +1145,7 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { @Override public ResultSet getIndexInfo(String catalog, final String schema, final String tbl, boolean unique, boolean approximate) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1409,7 +1409,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public ResultSet getSchemas(String catalog, final String schemaPtrn) throws SQLException { if (conn.isClosed()) - throw new SQLException("Connection is closed.", JdbcStateCode.CONNECTION_CLOSED); + throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class), diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index f265f8bdef932..e65b49c928e35 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -39,7 +39,7 @@ import java.sql.Timestamp; import java.util.ArrayList; import java.util.Calendar; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcMetaParamsResult; @@ -79,7 +79,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep ResultSet rs = getResultSet(); if (rs == null) - throw new SQLException("The query isn't SELECT query: " + sql, JdbcStateCode.PARSING_EXCEPTION); + throw new SQLException("The query isn't SELECT query: " + sql, SqlStateCode.PARSING_EXCEPTION); return rs; } @@ -87,7 +87,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep /** {@inheritDoc} */ @Override public ResultSet executeQuery(String sql) throws SQLException { throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -97,7 +97,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep int res = getUpdateCount(); if (res == -1) - throw new SQLException("The query is not DML statement: " + sql, JdbcStateCode.PARSING_EXCEPTION); + throw new SQLException("The query is not DML statement: " + sql, SqlStateCode.PARSING_EXCEPTION); return res; } @@ -105,25 +105,25 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep /** {@inheritDoc} */ @Override public int executeUpdate(String sql) throws SQLException { throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int columnIndexes[]) throws SQLException { throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, String columnNames[]) throws SQLException { throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " + - "instance.", JdbcStateCode.PARSING_EXCEPTION); + "instance.", SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -254,7 +254,7 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public boolean execute(String sql) throws SQLException { throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -275,7 +275,7 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public void addBatch(String sql) throws SQLException { throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance.", - JdbcStateCode.PARSING_EXCEPTION); + SqlStateCode.PARSING_EXCEPTION); } /** {@inheritDoc} */ @@ -521,7 +521,7 @@ private void setArgument(int paramIdx, Object val) throws SQLException { if (val != null && !SqlListenerUtils.isPlainType(val.getClass())) throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']', - JdbcStateCode.INVALID_PARAMETER_VALUE); + SqlStateCode.INVALID_PARAMETER_VALUE); if (paramIdx < 1) throw new SQLException("Parameter index is invalid: " + paramIdx); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index b8b9c0e949996..410e9a32cdaa3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -46,7 +46,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; @@ -280,11 +280,11 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()) != 0; } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to boolean: " + val, JdbcStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to boolean: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -305,11 +305,11 @@ else if (cls == String.class || cls == Character.class) { return Byte.parseByte(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to byte: " + val, JdbcStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to byte: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -330,12 +330,12 @@ else if (cls == String.class || cls == Character.class) { return Short.parseShort(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to short: " + val, JdbcStateCode.DATA_EXCEPTION, + throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to short: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -356,12 +356,12 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to int: " + val, JdbcStateCode.DATA_EXCEPTION, + throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to int: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -382,12 +382,12 @@ else if (cls == String.class || cls == Character.class) { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to long: " + val, JdbcStateCode.DATA_EXCEPTION, + throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to long: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -408,12 +408,12 @@ else if (cls == String.class || cls == Character.class) { return Float.parseFloat(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to float: " + val, JdbcStateCode.DATA_EXCEPTION, + throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to float: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -434,12 +434,12 @@ else if (cls == String.class || cls == Character.class) { return Double.parseDouble(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to double: " + val, JdbcStateCode.DATA_EXCEPTION, + throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to double: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -481,7 +481,7 @@ else if (cls == Long.class) { else if (cls == String.class) return ((String)val).getBytes(); else - throw new SQLException("Cannot convert to byte[]: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to byte[]: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -498,7 +498,7 @@ else if (cls == String.class) else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class) return new Date(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to date: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to date: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -515,7 +515,7 @@ else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class) return new Time(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to time: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to time: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -532,7 +532,7 @@ else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class) return new Timestamp(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to timestamp: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to timestamp: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -551,11 +551,11 @@ else if (cls == String.class) { return new URL(val.toString()); } catch (MalformedURLException e) { - throw new SQLException("Cannot convert to URL: " + val, JdbcStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to URL: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.DATA_EXCEPTION); } @@ -740,7 +740,7 @@ else if (cls == String.class) { Integer order = columnOrder().get(colLb.toUpperCase()); if (order == null) - throw new SQLException("Column not found: " + colLb, JdbcStateCode.PARSING_EXCEPTION); + throw new SQLException("Column not found: " + colLb, SqlStateCode.PARSING_EXCEPTION); assert order >= 0; @@ -782,11 +782,11 @@ else if (cls == String.class || cls == Character.class) { } catch (ParseException e) { throw new SQLException("Cannot convert to BigDecimal: " + val, - JdbcStateCode.DATA_EXCEPTION, e); + SqlStateCode.DATA_EXCEPTION, e); } } else - throw new SQLException("Cannot convert to BigDecimal: " + val, JdbcStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.DATA_EXCEPTION); } /** {@inheritDoc} */ @@ -1823,7 +1823,7 @@ else if (targetCls == URL.class) return val; else throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val, - JdbcStateCode.DATA_EXCEPTION); + SqlStateCode.DATA_EXCEPTION); } } @@ -1847,7 +1847,7 @@ private Object getValue(int colIdx) throws SQLException { return val; } catch (IndexOutOfBoundsException e) { - throw new SQLException("Invalid column index: " + colIdx, JdbcStateCode.PARSING_EXCEPTION, e); + throw new SQLException("Invalid column index: " + colIdx, SqlStateCode.PARSING_EXCEPTION, e); } } @@ -1858,7 +1858,7 @@ private Object getValue(int colIdx) throws SQLException { */ private void ensureNotClosed() throws SQLException { if (closed) - throw new SQLException("Result set is closed.", JdbcStateCode.INVALID_CURSOR_STATE); + throw new SQLException("Result set is closed.", SqlStateCode.INVALID_CURSOR_STATE); } /** @@ -1877,7 +1877,7 @@ private void ensureHasCurrentRow() throws SQLException { */ private List meta() throws SQLException { if (finished && (!isQuery || autoClose)) - throw new SQLException("Server cursor is already closed.", JdbcStateCode.INVALID_CURSOR_STATE); + throw new SQLException("Server cursor is already closed.", SqlStateCode.INVALID_CURSOR_STATE); if (!metaInit) { JdbcQueryMetadataResult res = stmt.conn.sendRequest(new JdbcQueryMetadataRequest(qryId)); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index f98d9ae63fec9..39c1cbd5a1066 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -27,7 +27,7 @@ import java.util.ArrayList; import java.util.List; import org.apache.ignite.cache.query.SqlQuery; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteResult; @@ -97,7 +97,7 @@ public class JdbcThinStatement implements Statement { ResultSet rs = getResultSet(); if (rs == null) - throw new SQLException("The query isn't SELECT query: " + sql, JdbcStateCode.PARSING_EXCEPTION); + throw new SQLException("The query isn't SELECT query: " + sql, SqlStateCode.PARSING_EXCEPTION); return rs; } @@ -139,7 +139,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg int res = getUpdateCount(); if (res == -1) - throw new SQLException("The query is not DML statememt: " + sql, JdbcStateCode.PARSING_EXCEPTION); + throw new SQLException("The query is not DML statememt: " + sql, SqlStateCode.PARSING_EXCEPTION); return res; } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java index dafb8db5ed066..8e5af31820db7 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java @@ -20,7 +20,7 @@ import java.sql.SQLException; import javax.cache.processor.EntryProcessor; import org.apache.ignite.IgniteCache; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; /** * Error codes for query operations. @@ -126,17 +126,17 @@ public static SQLException createJdbcSqlException(String msg, int code) { public static String codeToSqlState(int statusCode) { switch (statusCode) { case DUPLICATE_KEY: - return JdbcStateCode.CONSTRAINT_VIOLATION; + return SqlStateCode.CONSTRAINT_VIOLATION; case NULL_KEY: case NULL_VALUE: - return JdbcStateCode.NULL_VALUE; + return SqlStateCode.NULL_VALUE; case UNSUPPORTED_OPERATION: - return JdbcStateCode.UNSUPPORTED_OPERATION; + return SqlStateCode.UNSUPPORTED_OPERATION; case CONVERSION_FAILED: - return JdbcStateCode.CONVERSION_FAILED; + return SqlStateCode.CONVERSION_FAILED; case PARSING: case TABLE_NOT_FOUND: @@ -149,10 +149,10 @@ public static String codeToSqlState(int statusCode) { case UNEXPECTED_OPERATION: case UNEXPECTED_ELEMENT_TYPE: case KEY_UPDATE: - return JdbcStateCode.PARSING_EXCEPTION; + return SqlStateCode.PARSING_EXCEPTION; default: - return JdbcStateCode.INTERNAL_ERROR; + return SqlStateCode.INTERNAL_ERROR; } } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java similarity index 94% rename from modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java rename to modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java index 0d0e73c361e0a..9130d7761ef31 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcStateCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java @@ -15,18 +15,18 @@ * limitations under the License. */ -package org.apache.ignite.internal.jdbc2; +package org.apache.ignite.internal.processors.odbc; import java.sql.ResultSet; /** - * Error codes to throw from JDBC driver (SQLSTATE codes). + * SQL state codes. */ -public final class JdbcStateCode { +public final class SqlStateCode { /** * No-op constructor to prevent instantiation. */ - private JdbcStateCode() { + private SqlStateCode() { // No-op. } diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java index f099b997ab382..cbaa478563513 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/DmlStatementsProcessor.java @@ -49,7 +49,7 @@ import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.cluster.ClusterNode; import org.apache.ignite.internal.GridKernalContext; -import org.apache.ignite.internal.jdbc2.JdbcStateCode; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.affinity.AffinityTopologyVersion; import org.apache.ignite.internal.processors.cache.CacheOperationContext; import org.apache.ignite.internal.processors.cache.GridCacheAdapter; @@ -848,7 +848,7 @@ private long doInsert(UpdatePlan plan, Iterable> cursor, int pageSize) t String msg = "Failed to INSERT some keys because they are already in cache " + "[keys=" + sender.failedKeys() + ']'; - SQLException dupEx = new SQLException(msg, JdbcStateCode.CONSTRAINT_VIOLATION); + SQLException dupEx = new SQLException(msg, SqlStateCode.CONSTRAINT_VIOLATION); if (resEx == null) resEx = dupEx; From f4b548ff185e081b3ad40340df2f6de39397e642 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:35:17 +0300 Subject: [PATCH 23/43] Cosmetics. --- .../internal/processors/odbc/jdbc/JdbcRequestHandler.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index 249f505f3a459..32dd8b51ce24a 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -272,8 +272,7 @@ private JdbcResponse executeQuery(JdbcQueryExecuteRequest req) { qry.setLazy(lazy); if (req.pageSize() <= 0) - return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, - "Invalid fetch size : [fetchSize=" + req.pageSize() + ']'); + return new JdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Invalid fetch size: " + req.pageSize()); qry.setPageSize(req.pageSize()); @@ -460,10 +459,12 @@ private SqlListenerResponse executeBatch(JdbcBatchExecuteRequest req) { if (e instanceof IgniteSQLException) { code = ((IgniteSQLException) e).statusCode(); + msg = e.getMessage(); } else { code = IgniteQueryErrorCode.UNKNOWN; + msg = e.getMessage(); } @@ -691,6 +692,7 @@ private static boolean matches(String str, String ptrn) { /** * Create {@link JdbcResponse} bearing appropriate Ignite specific result code if possible * from given {@link Exception}. + * * @param e Exception to convert. * @return resulting {@link JdbcResponse}. */ From 4df93a0c15e8ec4dff20277db6a8862f296feeaf Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:53:38 +0300 Subject: [PATCH 24/43] Minors. --- .../internal/processors/odbc/jdbc/JdbcConnectionContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java index f737a5c1f9eb6..1f13fcfc295ae 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcConnectionContext.java @@ -101,7 +101,7 @@ public JdbcConnectionContext(GridKernalContext ctx, GridSpinBusyLock busyLock, i lazyExec = reader.readBoolean(); handler = new JdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, - enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec); + enforceJoinOrder, collocated, replicatedOnly, autoCloseCursors, lazyExec); parser = new JdbcMessageParser(ctx); } From c09da87d150051b85f80d07ff1fb5a24c0e809e5 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 11:53:59 +0300 Subject: [PATCH 25/43] Minors. --- .../main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java index eeaf5b7cca4d9..37304fc960589 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc2/JdbcUtils.java @@ -22,6 +22,7 @@ import java.sql.Timestamp; import java.sql.Types; import java.util.Date; + import org.apache.ignite.internal.processors.query.QueryUtils; import static java.sql.Types.BIGINT; From 713deca174d0a5ac48daeaefe33a04d2703d09f2 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:10:41 +0300 Subject: [PATCH 26/43] Better encapsulation in JdbcThinTcpIo. --- .../jdbc/thin/JdbcThinConnection.java | 27 +---------- .../internal/jdbc/thin/JdbcThinTcpIo.java | 45 ++++++++++++++++--- 2 files changed, 39 insertions(+), 33 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index f562452e8b53a..7c095578a61a3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -40,10 +40,6 @@ import java.util.logging.Logger; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.processors.odbc.SqlStateCode; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; import org.apache.ignite.internal.processors.query.IgniteSQLException; @@ -54,11 +50,6 @@ import static java.sql.ResultSet.CONCUR_READ_ONLY; import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; import static java.sql.ResultSet.TYPE_FORWARD_ONLY; -import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.DYNAMIC_SIZE_MSG_CAP; -import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.MAX_BATCH_QRY_CNT; -import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_CLOSE_MSG_SIZE; -import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_FETCH_MSG_SIZE; -import static org.apache.ignite.internal.jdbc.thin.JdbcThinTcpIo.QUERY_META_MSG_SIZE; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_AUTO_CLOSE_SERVER_CURSORS; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_COLLOCATED; import static org.apache.ignite.internal.jdbc.thin.JdbcThinUtils.PROP_DISTRIBUTED_JOINS; @@ -669,24 +660,8 @@ boolean autoCloseServerCursor() { * @throws SQLException On any error. */ R sendRequest(JdbcRequest req) throws SQLException { - int cap; - - if (req instanceof JdbcBatchExecuteRequest) { - int cnt = Math.min(MAX_BATCH_QRY_CNT, ((JdbcBatchExecuteRequest)req).queries().size()); - - cap = cnt * DYNAMIC_SIZE_MSG_CAP; - } - else if (req instanceof JdbcQueryCloseRequest) - cap = QUERY_CLOSE_MSG_SIZE; - else if (req instanceof JdbcQueryMetadataRequest) - cap = QUERY_META_MSG_SIZE; - else if (req instanceof JdbcQueryFetchRequest) - cap = QUERY_FETCH_MSG_SIZE; - else - cap = DYNAMIC_SIZE_MSG_CAP; - try { - return cliIo.sendRequest(req, cap); + return cliIo.sendRequest(req); } catch (IgniteSQLException e) { throw e.toJdbcException(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index 8ae3e650d448c..8eb0d11bc2c47 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -32,6 +32,10 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; @@ -54,19 +58,19 @@ public class JdbcThinTcpIo { private static final int HANDSHAKE_MSG_SIZE = 13; /** Initial output for query message. */ - static final int DYNAMIC_SIZE_MSG_CAP = 256; + private static final int DYNAMIC_SIZE_MSG_CAP = 256; /** Maximum batch query count. */ - static final int MAX_BATCH_QRY_CNT = 32; + private static final int MAX_BATCH_QRY_CNT = 32; /** Initial output for query fetch message. */ - static final int QUERY_FETCH_MSG_SIZE = 13; + private static final int QUERY_FETCH_MSG_SIZE = 13; /** Initial output for query fetch message. */ - static final int QUERY_META_MSG_SIZE = 9; + private static final int QUERY_META_MSG_SIZE = 9; /** Initial output for query close message. */ - static final int QUERY_CLOSE_MSG_SIZE = 9; + private static final int QUERY_CLOSE_MSG_SIZE = 9; /** Host. */ private final String host; @@ -295,13 +299,14 @@ public void handshake_2_1_0() throws IOException, IgniteCheckedException { /** * @param req Request. - * @param cap Initial output stream capacity. * @return Server response. * @throws IOException On IO error. * @throws IgniteCheckedException On error. */ @SuppressWarnings("unchecked") - R sendRequest(JdbcRequest req, int cap) throws IOException, IgniteCheckedException { + R sendRequest(JdbcRequest req) throws IOException, IgniteCheckedException { + int cap = guessCapacity(req); + BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null); req.writeBinary(writer); @@ -320,6 +325,32 @@ R sendRequest(JdbcRequest req, int cap) throws IOExceptio return (R)res.response(); } + /** + * Try to guess request capacity. + * + * @param req Request. + * @return Expected capacity. + */ + private static int guessCapacity(JdbcRequest req) { + int cap; + + if (req instanceof JdbcBatchExecuteRequest) { + int cnt = Math.min(MAX_BATCH_QRY_CNT, ((JdbcBatchExecuteRequest)req).queries().size()); + + cap = cnt * DYNAMIC_SIZE_MSG_CAP; + } + else if (req instanceof JdbcQueryCloseRequest) + cap = QUERY_CLOSE_MSG_SIZE; + else if (req instanceof JdbcQueryMetadataRequest) + cap = QUERY_META_MSG_SIZE; + else if (req instanceof JdbcQueryFetchRequest) + cap = QUERY_FETCH_MSG_SIZE; + else + cap = DYNAMIC_SIZE_MSG_CAP; + + return cap; + } + /** * @param req JDBC request bytes. * @throws IOException On error. From 9085efda6a040ee430bb83ad06780f58d6df22d1 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:20:05 +0300 Subject: [PATCH 27/43] Better encapsulation. --- .../jdbc/thin/JdbcThinConnection.java | 21 ++++++++++++----- .../internal/jdbc/thin/JdbcThinTcpIo.java | 23 ++++++------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 7c095578a61a3..bd0ed85f48a1e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -38,11 +38,12 @@ import java.util.Properties; import java.util.concurrent.Executor; import java.util.logging.Logger; -import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; +import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.lang.IgniteProductVersion; @@ -659,19 +660,27 @@ boolean autoCloseServerCursor() { * @return Server response. * @throws SQLException On any error. */ + @SuppressWarnings("unchecked") R sendRequest(JdbcRequest req) throws SQLException { try { - return cliIo.sendRequest(req); + JdbcResponse res = cliIo.sendRequest(req); + + if (res.status() != SqlListenerResponse.STATUS_SUCCESS) + throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status())); + + return (R)res.response(); } - catch (IgniteSQLException e) { - throw e.toJdbcException(); + catch (SQLException e) { + throw e; } catch (IOException e) { close(); throw new SQLException("Failed to send Ignite JDBC request.", SqlStateCode.CONNECTION_FAILURE, e); } - catch (IgniteCheckedException e) { + catch (Exception e) { + close(); + throw new SQLException("Failed to send Ignite JDBC request.", e); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index 8eb0d11bc2c47..4881c2055910f 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -22,24 +22,21 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; + import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.binary.BinaryReaderExImpl; import org.apache.ignite.internal.binary.BinaryWriterExImpl; import org.apache.ignite.internal.binary.streams.BinaryHeapInputStream; import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener; import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; -import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; -import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResult; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.ipc.loopback.IpcClientTcpEndpoint; import org.apache.ignite.internal.util.typedef.internal.U; import org.apache.ignite.lang.IgniteProductVersion; @@ -300,11 +297,10 @@ public void handshake_2_1_0() throws IOException, IgniteCheckedException { /** * @param req Request. * @return Server response. - * @throws IOException On IO error. - * @throws IgniteCheckedException On error. + * @throws IOException In case of IO error. */ @SuppressWarnings("unchecked") - R sendRequest(JdbcRequest req) throws IOException, IgniteCheckedException { + JdbcResponse sendRequest(JdbcRequest req) throws IOException { int cap = guessCapacity(req); BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(cap), null, null); @@ -319,10 +315,7 @@ R sendRequest(JdbcRequest req) throws IOException, Ignite res.readBinary(reader); - if (res.status() != SqlListenerResponse.STATUS_SUCCESS) - throw new IgniteSQLException(res.error(), res.status(), IgniteQueryErrorCode.codeToSqlState(res.status())); - - return (R)res.response(); + return res; } /** @@ -371,9 +364,8 @@ private void send(byte[] req) throws IOException { /** * @return Bytes of a response from server. * @throws IOException On error. - * @throws IgniteCheckedException On error. */ - private byte[] read() throws IOException, IgniteCheckedException { + private byte[] read() throws IOException { byte[] sizeBytes = read(4); int msgSize = (((0xFF & sizeBytes[3]) << 24) | ((0xFF & sizeBytes[2]) << 16) @@ -386,9 +378,8 @@ private byte[] read() throws IOException, IgniteCheckedException { * @param size Count of bytes to read from stream. * @return Read bytes. * @throws IOException On error. - * @throws IgniteCheckedException On error. */ - private byte [] read(int size) throws IOException, IgniteCheckedException { + private byte [] read(int size) throws IOException { int off = 0; byte[] data = new byte[size]; @@ -397,7 +388,7 @@ private byte[] read() throws IOException, IgniteCheckedException { int res = in.read(data, off, size - off); if (res == -1) - throw new IgniteCheckedException("Failed to read incoming message (not enough data)."); + throw new IOException("Failed to read incoming message (not enough data)."); off += res; } From 5ef5099b8e3177798a4ce880a5d5498b13864be0 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:24:27 +0300 Subject: [PATCH 28/43] Cosmetics. --- .../org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 39c1cbd5a1066..dd7de81665331 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -128,7 +128,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg assert res != null; - rs = new JdbcThinResultSet(JdbcThinStatement.this, res.getQueryId(), pageSize, res.last(), res.items(), + rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), res.isQuery(), conn.autoCloseServerCursor(), res.updateCount(), closeOnCompletion); } From 9465a2fca99911aeb6ae58d8d910d1869cdab049 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:27:22 +0300 Subject: [PATCH 29/43] Fixed JdbcThinPreparedStatement SQLSTATE for unsupported operations. --- .../jdbc/thin/JdbcThinPreparedStatement.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java index e65b49c928e35..ce1b65caec0eb 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -87,7 +87,7 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep /** {@inheritDoc} */ @Override public ResultSet executeQuery(String sql) throws SQLException { throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @@ -105,25 +105,25 @@ public class JdbcThinPreparedStatement extends JdbcThinStatement implements Prep /** {@inheritDoc} */ @Override public int executeUpdate(String sql) throws SQLException { throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw new SQLException("The method 'executeUpdate(String, int)' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, int columnIndexes[]) throws SQLException { throw new SQLException("The method 'executeUpdate(String, int[])' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @Override public int executeUpdate(String sql, String columnNames[]) throws SQLException { throw new SQLException("The method 'executeUpdate(String, String[])' is called on PreparedStatement " + - "instance.", SqlStateCode.PARSING_EXCEPTION); + "instance.", SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @@ -254,7 +254,7 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public boolean execute(String sql) throws SQLException { throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ @@ -275,7 +275,7 @@ private void executeWithArguments(JdbcStatementType stmtType) throws SQLExceptio /** {@inheritDoc} */ @Override public void addBatch(String sql) throws SQLException { throw new SQLException("The method 'addBatch(String)' is called on PreparedStatement instance.", - SqlStateCode.PARSING_EXCEPTION); + SqlStateCode.UNSUPPORTED_OPERATION); } /** {@inheritDoc} */ From 8f912e15316b2a3ededc7724e543fb4446e4549e Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:29:03 +0300 Subject: [PATCH 30/43] Cosmetics. --- .../jdbc/thin/JdbcThinDatabaseMetadata.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index d095ef5faa940..f44b1d64d408c 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -706,8 +706,8 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { } /** {@inheritDoc} */ - @Override public ResultSet getTables(String catalog, final String schemaPtrn, final String tblNamePtrn, - String[] tblTypes) throws SQLException { + @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, String[] tblTypes) + throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); @@ -791,8 +791,8 @@ private List tableRow(JdbcTableMeta tblMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getColumns(String catalog, final String schemaPtrn, final String tblNamePtrn, - final String colNamePtrn) throws SQLException { + @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, String colNamePtrn) + throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); @@ -1142,8 +1142,8 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getIndexInfo(String catalog, final String schema, final String tbl, boolean unique, - boolean approximate) throws SQLException { + @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique, + boolean approximate) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); @@ -1407,7 +1407,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { } /** {@inheritDoc} */ - @Override public ResultSet getSchemas(String catalog, final String schemaPtrn) throws SQLException { + @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException { if (conn.isClosed()) throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); From 5709e90a67ef2170703969e59d70f1bc42f84e2d Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:29:25 +0300 Subject: [PATCH 31/43] Fixed bug in JdbcThinStatement.ensureNotClosed. --- .../org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index dd7de81665331..2459aadcbdaaf 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -563,6 +563,6 @@ JdbcThinConnection connection() { */ protected void ensureNotClosed() throws SQLException { if (isClosed()) - throw new SQLException("Statement is closed."); + throw new SQLException("Statement is closed.", SqlStateCode.CONNECTION_CLOSED); } } From 7b0e05bc1c57299d7386a61683abea303a352f8e Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:32:09 +0300 Subject: [PATCH 32/43] Cosmetics. --- .../ignite/internal/jdbc/thin/JdbcThinConnection.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index bd0ed85f48a1e..0ab948accc081 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -146,7 +146,7 @@ public JdbcThinConnection(String url, Properties props, String schema) throws SQ catch (Exception e) { cliIo.close(); - throw new SQLException("Failed to connect to Ignite node [host=" + host + ", port=" + port + ']', + throw new SQLException("Failed to connect to Ignite cluster [host=" + host + ", port=" + port + ']', SqlStateCode.CLIENT_CONNECTION_FAILED, e); } } @@ -559,7 +559,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null.", SqlStateCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null."); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -569,7 +569,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, ensureNotClosed(); if (typeName == null) - throw new SQLException("Type name cannot be null.", SqlStateCode.INVALID_DATA_TYPE); + throw new SQLException("Type name cannot be null."); throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); } @@ -676,12 +676,12 @@ R sendRequest(JdbcRequest req) throws SQLException { catch (IOException e) { close(); - throw new SQLException("Failed to send Ignite JDBC request.", SqlStateCode.CONNECTION_FAILURE, e); + throw new SQLException("Failed to communicate with Ignite cluster.", SqlStateCode.CONNECTION_FAILURE, e); } catch (Exception e) { close(); - throw new SQLException("Failed to send Ignite JDBC request.", e); + throw new SQLException("Failed to communicate with Ignite cluster.", e); } } From 33de27e0b1a32e7d773cb2a3315e01d91b7a95d2 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 12:35:31 +0300 Subject: [PATCH 33/43] Cosmetics. --- .../internal/jdbc/thin/JdbcThinConnection.java | 2 +- .../internal/jdbc/thin/JdbcThinResultSet.java | 18 ++++++------------ 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index 0ab948accc081..eb2f52f738765 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -753,7 +753,7 @@ else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal)) return false; else throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); + ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); } /** diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index 410e9a32cdaa3..e776d32a1e902 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -330,8 +330,7 @@ else if (cls == String.class || cls == Character.class) { return Short.parseShort(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION, - e); + throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else @@ -356,8 +355,7 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION, - e); + throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else @@ -382,8 +380,7 @@ else if (cls == String.class || cls == Character.class) { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION, - e); + throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else @@ -408,8 +405,7 @@ else if (cls == String.class || cls == Character.class) { return Float.parseFloat(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION, - e); + throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else @@ -434,8 +430,7 @@ else if (cls == String.class || cls == Character.class) { return Double.parseDouble(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION, - e); + throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else @@ -781,8 +776,7 @@ else if (cls == String.class || cls == Character.class) { return (BigDecimal)decimalFormat.get().parse(val.toString()); } catch (ParseException e) { - throw new SQLException("Cannot convert to BigDecimal: " + val, - SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.DATA_EXCEPTION, e); } } else From b02468d03fb6df8dce76b9df31baf8ee4bfcece2 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 13:40:24 +0300 Subject: [PATCH 34/43] Fixing tests. --- .../internal/jdbc2/JdbcInsertStatementSelfTest.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java index 2cd0c5a827c55..44a45b7323b4a 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcInsertStatementSelfTest.java @@ -164,15 +164,12 @@ public void testDuplicateKeys() { } }, SQLException.class, null); - assertNotNull(reason.getCause()); - - reason = reason.getCause().getCause(); + reason = reason.getCause(); assertNotNull(reason); - assertEquals(SQLException.class, reason.getClass()); - - assertEquals("Failed to INSERT some keys because they are already in cache [keys=[p2]]", reason.getMessage()); + assertTrue(reason.getMessage().contains( + "Failed to INSERT some keys because they are already in cache [keys=[p2]]")); assertEquals(3, jcache(0).withKeepBinary().getAll(new HashSet<>(Arrays.asList("p1", "p2", "p3"))).size()); } From 95b4f464a2f713ec9bb122d4c63c02bed000ff38 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 13:42:45 +0300 Subject: [PATCH 35/43] Fixing tests. --- .../internal/jdbc2/JdbcErrorsSelfTest.java | 36 ------------------- 1 file changed, 36 deletions(-) delete mode 100644 modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java deleted file mode 100644 index 47aa6a195e92b..0000000000000 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcErrorsSelfTest.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.ignite.internal.jdbc2; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import org.apache.ignite.jdbc.JdbcErrorsAbstractSelfTest; - -/** - * Test SQLSTATE codes propagation with "JDBC2" driver. - */ -public class JdbcErrorsSelfTest extends JdbcErrorsAbstractSelfTest { - /** Path to JDBC configuration for node that is to start. */ - private static final String CFG_PATH = "modules/clients/src/test/config/jdbc-config.xml"; - - /** {@inheritDoc} */ - @Override protected Connection getConnection() throws SQLException { - return DriverManager.getConnection("jdbc:ignite:cfg://cache=test@" + CFG_PATH); - } -} From ebd7c68d4f65db95c635592b7083a30ff800e765 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 13:45:41 +0300 Subject: [PATCH 36/43] Fixing tests. --- .../internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java index c6658223b043c..cf9f7a9bfe25b 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java @@ -321,9 +321,6 @@ private static void assertSqlException(RunnableX r, int expCode) { r.run(); } catch (SQLException e) { - assertEquals("Unexpected error code [expected=" + expCode + ", actual=" + e.getErrorCode() + ']', - expCode, e.getErrorCode()); - return; } catch (Exception e) { From c61fac2c16a90250ecb98828998da0051bbb9ca4 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 13:46:10 +0300 Subject: [PATCH 37/43] Fixing tests. --- .../jdbc2/JdbcDynamicIndexAbstractSelfTest.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java index cf9f7a9bfe25b..9485d0d54212c 100644 --- a/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/internal/jdbc2/JdbcDynamicIndexAbstractSelfTest.java @@ -23,7 +23,6 @@ import java.sql.Statement; import java.util.Collections; import java.util.List; -import javax.cache.CacheException; import org.apache.ignite.IgniteCache; import org.apache.ignite.cache.CacheAtomicityMode; import org.apache.ignite.cache.CacheMode; @@ -31,8 +30,6 @@ import org.apache.ignite.cache.query.SqlFieldsQuery; import org.apache.ignite.configuration.CacheConfiguration; import org.apache.ignite.configuration.NearCacheConfiguration; -import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; -import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.typedef.F; /** @@ -176,7 +173,7 @@ public void testCreateIndexWithDuplicateName() throws SQLException { @Override public void run() throws Exception { jdbcRun(CREATE_INDEX); } - }, IgniteQueryErrorCode.INDEX_ALREADY_EXISTS); + }); } /** @@ -227,7 +224,7 @@ public void testDropMissingIndex() { @Override public void run() throws Exception { jdbcRun(DROP_INDEX); } - }, IgniteQueryErrorCode.INDEX_NOT_FOUND); + }); } /** @@ -312,9 +309,8 @@ private IgniteCache cache() { * Ensure that SQL exception is thrown. * * @param r Runnable. - * @param expCode Error code. */ - private static void assertSqlException(RunnableX r, int expCode) { + private static void assertSqlException(RunnableX r) { // We expect IgniteSQLException with given code inside CacheException inside JDBC SQLException. try { From 07ab48298c886d594de354d3f009baf775a5d728 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 14:28:00 +0300 Subject: [PATCH 38/43] Fixing compilation. --- .../org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java index bbcfb5a7edaf7..424ec21e41385 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java @@ -106,7 +106,6 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcBlobTest.class)); suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcStreamingSelfTest.class)); - suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcErrorsSelfTest.class)); // DDL tests. suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDynamicIndexAtomicPartitionedNearSelfTest.class)); From e7b3dd056e30335478d376d9024faab8de04b722 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Fri, 15 Sep 2017 14:38:49 +0300 Subject: [PATCH 39/43] IGNITE-5620 Fixes --- .../jdbc/suite/IgniteJdbcDriverTestSuite.java | 1 - .../jdbc/thin/JdbcThinConnection.java | 20 +++----- .../internal/jdbc/thin/JdbcThinResultSet.java | 46 +++++++++---------- .../internal/jdbc/thin/JdbcThinTcpIo.java | 43 +++++++++-------- .../processors/odbc/SqlStateCode.java | 14 ++---- 5 files changed, 56 insertions(+), 68 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java index bbcfb5a7edaf7..424ec21e41385 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverTestSuite.java @@ -106,7 +106,6 @@ public static TestSuite suite() throws Exception { suite.addTest(new TestSuite(JdbcBlobTest.class)); suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcStreamingSelfTest.class)); - suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcErrorsSelfTest.class)); // DDL tests. suite.addTest(new TestSuite(org.apache.ignite.internal.jdbc2.JdbcDynamicIndexAtomicPartitionedNearSelfTest.class)); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index eb2f52f738765..d55a6f9c571d4 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -17,7 +17,6 @@ package org.apache.ignite.internal.jdbc.thin; -import java.io.IOException; import java.sql.Array; import java.sql.Blob; import java.sql.CallableStatement; @@ -673,15 +672,10 @@ R sendRequest(JdbcRequest req) throws SQLException { catch (SQLException e) { throw e; } - catch (IOException e) { - close(); - - throw new SQLException("Failed to communicate with Ignite cluster.", SqlStateCode.CONNECTION_FAILURE, e); - } catch (Exception e) { close(); - throw new SQLException("Failed to communicate with Ignite cluster.", e); + throw new SQLException("Failed to communicate with Ignite cluster.", SqlStateCode.CONNECTION_FAILURE, e); } } @@ -699,7 +693,7 @@ private static String extractHost(Properties props) throws SQLException { host = host.trim(); if (F.isEmpty(host)) - throw new SQLException("Host name is empty.", SqlStateCode.CONNECTION_ERROR); + throw new SQLException("Host name is empty.", SqlStateCode.CLIENT_CONNECTION_FAILED); return host; } @@ -723,10 +717,10 @@ private static int extractPort(Properties props) throws SQLException { port = Integer.parseInt(portStr); if (port <= 0 || port > 0xFFFF) - throw new SQLException("Invalid port: " + portStr, SqlStateCode.CONNECTION_ERROR); + throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED); } catch (NumberFormatException e) { - throw new SQLException("Invalid port: " + portStr, SqlStateCode.CONNECTION_ERROR); + throw new SQLException("Invalid port: " + portStr, SqlStateCode.CLIENT_CONNECTION_FAILED); } return port; @@ -753,7 +747,7 @@ else if (Boolean.FALSE.toString().equalsIgnoreCase(strVal)) return false; else throw new SQLException("Failed to parse boolean property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); + ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED); } /** @@ -770,7 +764,7 @@ private static int extractIntNonNegative(Properties props, String propName, int if (res < 0) throw new SQLException("Property cannot be negative [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + res + ']', SqlStateCode.CONNECTION_ERROR); + ", value=" + res + ']', SqlStateCode.CLIENT_CONNECTION_FAILED); return res; } @@ -795,7 +789,7 @@ private static int extractInt(Properties props, String propName, int dfltVal) th } catch (NumberFormatException e) { throw new SQLException("Failed to parse int property [name=" + JdbcThinUtils.trimPrefix(propName) + - ", value=" + strVal + ']', SqlStateCode.CONNECTION_ERROR); + ", value=" + strVal + ']', SqlStateCode.CLIENT_CONNECTION_FAILED); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java index e776d32a1e902..189175be41e42 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -280,11 +280,11 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()) != 0; } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to boolean: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -305,11 +305,11 @@ else if (cls == String.class || cls == Character.class) { return Byte.parseByte(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to byte: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -330,11 +330,11 @@ else if (cls == String.class || cls == Character.class) { return Short.parseShort(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to short: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to short: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -355,11 +355,11 @@ else if (cls == String.class || cls == Character.class) { return Integer.parseInt(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to int: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to int: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -380,11 +380,11 @@ else if (cls == String.class || cls == Character.class) { return Long.parseLong(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to long: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to long: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -405,11 +405,11 @@ else if (cls == String.class || cls == Character.class) { return Float.parseFloat(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to float: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to float: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -430,11 +430,11 @@ else if (cls == String.class || cls == Character.class) { return Double.parseDouble(val.toString()); } catch (NumberFormatException e) { - throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to double: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to double: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -476,7 +476,7 @@ else if (cls == Long.class) { else if (cls == String.class) return ((String)val).getBytes(); else - throw new SQLException("Cannot convert to byte[]: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to byte[]: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -493,7 +493,7 @@ else if (cls == String.class) else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.class) return new Date(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to date: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to date: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -510,7 +510,7 @@ else if (cls == java.util.Date.class || cls == Time.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.class) return new Time(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to time: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to time: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -527,7 +527,7 @@ else if (cls == java.util.Date.class || cls == Date.class || cls == Timestamp.cl else if (cls == java.util.Date.class || cls == Date.class || cls == Time.class) return new Timestamp(((java.util.Date)val).getTime()); else - throw new SQLException("Cannot convert to timestamp: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to timestamp: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -546,11 +546,11 @@ else if (cls == String.class) { return new URL(val.toString()); } catch (MalformedURLException e) { - throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to URL: " + val, SqlStateCode.CONVERSION_FAILED); } @@ -776,11 +776,11 @@ else if (cls == String.class || cls == Character.class) { return (BigDecimal)decimalFormat.get().parse(val.toString()); } catch (ParseException e) { - throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.DATA_EXCEPTION, e); + throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED, e); } } else - throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.DATA_EXCEPTION); + throw new SQLException("Cannot convert to BigDecimal: " + val, SqlStateCode.CONVERSION_FAILED); } /** {@inheritDoc} */ @@ -1817,7 +1817,7 @@ else if (targetCls == URL.class) return val; else throw new SQLException("Cannot convert to " + targetCls.getName() + ": " + val, - SqlStateCode.DATA_EXCEPTION); + SqlStateCode.CONVERSION_FAILED); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index 4881c2055910f..c26e06da019b1 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; - +import java.sql.SQLException; import org.apache.ignite.IgniteCheckedException; import org.apache.ignite.internal.binary.BinaryReaderExImpl; import org.apache.ignite.internal.binary.BinaryWriterExImpl; @@ -31,6 +31,7 @@ import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener; import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchRequest; @@ -152,10 +153,10 @@ public class JdbcThinTcpIo { } /** - * @throws IgniteCheckedException On error. + * @throws SQLException On connection error or reject. * @throws IOException On IO error in handshake. */ - public void start() throws IgniteCheckedException, IOException { + public void start() throws SQLException, IOException { Socket sock = new Socket(); if (sockSndBuf != 0) @@ -168,24 +169,25 @@ public void start() throws IgniteCheckedException, IOException { try { sock.connect(new InetSocketAddress(host, port)); - } - catch (IOException e) { - throw new IgniteCheckedException("Failed to connect to server [host=" + host + ", port=" + port + ']', e); - } - endpoint = new IpcClientTcpEndpoint(sock); + endpoint = new IpcClientTcpEndpoint(sock); - out = new BufferedOutputStream(endpoint.outputStream()); - in = new BufferedInputStream(endpoint.inputStream()); + out = new BufferedOutputStream(endpoint.outputStream()); + in = new BufferedInputStream(endpoint.inputStream()); + } + catch (IOException | IgniteCheckedException e) { + throw new SQLException("Failed to connect to server [host=" + host + ", port=" + port + ']', + SqlStateCode.CLIENT_CONNECTION_FAILED, e); + } handshake(); } /** - * @throws IOException On error. - * @throws IgniteCheckedException On error. + * @throws IOException On IO error. + * @throws SQLException On connection reject. */ - public void handshake() throws IOException, IgniteCheckedException { + public void handshake() throws IOException, SQLException { BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(HANDSHAKE_MSG_SIZE), null, null); @@ -241,8 +243,9 @@ public void handshake() throws IOException, IgniteCheckedException { if (VER_2_1_0.equals(srvProtocolVer)) handshake_2_1_0(); else { - throw new IgniteCheckedException("Handshake failed [driverProtocolVer=" + CURRENT_VER + - ", remoteNodeProtocolVer=" + srvProtocolVer + ", err=" + err + ']'); + throw new SQLException("Handshake failed [driverProtocolVer=" + CURRENT_VER + + ", remoteNodeProtocolVer=" + srvProtocolVer + ", err=" + err + ']', + SqlStateCode.CONNECTION_REJECTED); } } } @@ -250,10 +253,10 @@ public void handshake() throws IOException, IgniteCheckedException { /** * Compatibility handshake for server version 2.1.0 * - * @throws IOException On error. - * @throws IgniteCheckedException On error. + * @throws IOException On IO error. + * @throws SQLException On connection reject. */ - public void handshake_2_1_0() throws IOException, IgniteCheckedException { + private void handshake_2_1_0() throws IOException, SQLException { BinaryWriterExImpl writer = new BinaryWriterExImpl(null, new BinaryHeapOutputStream(HANDSHAKE_MSG_SIZE), null, null); @@ -289,8 +292,8 @@ public void handshake_2_1_0() throws IOException, IgniteCheckedException { SqlListenerProtocolVersion ver = SqlListenerProtocolVersion.create(maj, min, maintenance); - throw new IgniteCheckedException("Handshake failed [driverProtocolVer=" + CURRENT_VER + - ", remoteNodeProtocolVer=" + ver + ", err=" + err + ']'); + throw new SQLException("Handshake failed [driverProtocolVer=" + CURRENT_VER + + ", remoteNodeProtocolVer=" + ver + ", err=" + err + ']', SqlStateCode.CONNECTION_REJECTED); } } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java index 9130d7761ef31..eff680f48b718 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java @@ -17,8 +17,6 @@ package org.apache.ignite.internal.processors.odbc; -import java.sql.ResultSet; - /** * SQL state codes. */ @@ -30,21 +28,18 @@ private SqlStateCode() { // No-op. } - /** General connection establishment error. */ - public final static String CONNECTION_ERROR = "08000"; - /** Client has failed to open connection with specified server. */ public final static String CLIENT_CONNECTION_FAILED = "08001"; /** Connection unexpectedly turned out to be in closed state. */ public final static String CONNECTION_CLOSED = "08003"; + /** Connection was rejected by server. */ + public final static String CONNECTION_REJECTED = "08004"; + /** IO error during communication. */ public final static String CONNECTION_FAILURE = "08006"; - /** Value can't be converted to expected type (to be used in {@link ResultSet}'s {@code getXxx()} methods. */ - public final static String DATA_EXCEPTION = "22000"; - /** Null value occurred where it wasn't expected to. */ public final static String NULL_VALUE = "22004"; @@ -66,9 +61,6 @@ private SqlStateCode() { /** Requested operation is not supported. */ public final static String UNSUPPORTED_OPERATION = "0A000"; - /** Invalid data type. */ - public final static String INVALID_DATA_TYPE = "0D000"; - /** Parsing exception. */ public final static String PARSING_EXCEPTION = "42000"; From ce3a34cc6b37746115b2465c1607c696ff131750 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Fri, 15 Sep 2017 14:45:59 +0300 Subject: [PATCH 40/43] Test fix --- .../jdbc/thin/JdbcThinErrorsSelfTest.java | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java index 543a93ae28a27..706be2770b814 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinErrorsSelfTest.java @@ -67,7 +67,7 @@ public void testInvalidConnectionStringFormat() throws SQLException { return null; } - }, "08000"); + }, "08001"); } /* ALL TESTS PAST THIS POINT MUST BE MOVED TO PARENT CLASS JdbcErrorsAbstractSelfTest @@ -234,7 +234,7 @@ public void testInvalidIntFormat() throws SQLException { rs.getLong(1); } } - }, "22000"); + }, "0700B"); } /** @@ -253,7 +253,7 @@ public void testInvalidLongFormat() throws SQLException { rs.getLong(1); } } - }, "22000"); + }, "0700B"); } /** @@ -272,7 +272,7 @@ public void testInvalidFloatFormat() throws SQLException { rs.getFloat(1); } } - }, "22000"); + }, "0700B"); } /** @@ -291,7 +291,7 @@ public void testInvalidDoubleFormat() throws SQLException { rs.getDouble(1); } } - }, "22000"); + }, "0700B"); } /** @@ -310,7 +310,7 @@ public void testInvalidByteFormat() throws SQLException { rs.getByte(1); } } - }, "22000"); + }, "0700B"); } /** @@ -329,7 +329,7 @@ public void testInvalidShortFormat() throws SQLException { rs.getShort(1); } } - }, "22000"); + }, "0700B"); } /** @@ -348,7 +348,7 @@ public void testInvalidBigDecimalFormat() throws SQLException { rs.getBigDecimal(1); } } - }, "22000"); + }, "0700B"); } /** @@ -367,7 +367,7 @@ public void testInvalidBooleanFormat() throws SQLException { rs.getBoolean(1); } } - }, "22000"); + }, "0700B"); } /** @@ -386,7 +386,7 @@ public void testInvalidObjectFormat() throws SQLException { rs.getObject(1, List.class); } } - }, "22000"); + }, "0700B"); } /** @@ -405,7 +405,7 @@ public void testInvalidDateFormat() throws SQLException { rs.getDate(1); } } - }, "22000"); + }, "0700B"); } /** @@ -424,7 +424,7 @@ public void testInvalidTimeFormat() throws SQLException { rs.getTime(1); } } - }, "22000"); + }, "0700B"); } /** @@ -443,7 +443,7 @@ public void testInvalidTimestampFormat() throws SQLException { rs.getTimestamp(1); } } - }, "22000"); + }, "0700B"); } /** @@ -462,6 +462,6 @@ public void testInvalidUrlFormat() throws SQLException { rs.getURL(1); } } - }, "22000"); + }, "0700B"); } } From a7d0ecfdb9efd2154ea63a6322be117f36060673 Mon Sep 17 00:00:00 2001 From: devozerov Date: Fri, 15 Sep 2017 14:57:19 +0300 Subject: [PATCH 41/43] Fixed usages of CONNECTION_CLOSED. --- .../internal/jdbc/thin/JdbcThinConnection.java | 2 +- .../jdbc/thin/JdbcThinDatabaseMetadata.java | 16 +++++----------- .../internal/jdbc/thin/JdbcThinStatement.java | 4 ++-- 3 files changed, 8 insertions(+), 14 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index d55a6f9c571d4..a8faf6b6221ee 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -634,7 +634,7 @@ private void checkCursorOptions(int resSetType, int resSetConcurrency, * * @throws SQLException If connection is closed. */ - private void ensureNotClosed() throws SQLException { + public void ensureNotClosed() throws SQLException { if (closed) throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); } diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java index f44b1d64d408c..d13ef68d71a6d 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinDatabaseMetadata.java @@ -29,7 +29,6 @@ import java.util.LinkedList; import java.util.List; import org.apache.ignite.internal.IgniteVersionUtils; -import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.jdbc2.JdbcUtils; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcIndexMeta; @@ -708,8 +707,7 @@ public class JdbcThinDatabaseMetadata implements DatabaseMetaData { /** {@inheritDoc} */ @Override public ResultSet getTables(String catalog, String schemaPtrn, String tblNamePtrn, String[] tblTypes) throws SQLException { - if (conn.isClosed()) - throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); + conn.ensureNotClosed(); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -793,8 +791,7 @@ private List tableRow(JdbcTableMeta tblMeta) { /** {@inheritDoc} */ @Override public ResultSet getColumns(String catalog, String schemaPtrn, String tblNamePtrn, String colNamePtrn) throws SQLException { - if (conn.isClosed()) - throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); + conn.ensureNotClosed(); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -923,8 +920,7 @@ private List columnRow(JdbcColumnMeta colMeta, int pos) { /** {@inheritDoc} */ @Override public ResultSet getPrimaryKeys(String catalog, String schema, String tbl) throws SQLException { - if (conn.isClosed()) - throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); + conn.ensureNotClosed(); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1144,8 +1140,7 @@ private List> primaryKeyRows(JdbcPrimaryKeyMeta pkMeta) { /** {@inheritDoc} */ @Override public ResultSet getIndexInfo(String catalog, String schema, String tbl, boolean unique, boolean approximate) throws SQLException { - if (conn.isClosed()) - throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); + conn.ensureNotClosed(); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_CAT", String.class), @@ -1408,8 +1403,7 @@ private List> indexRows(JdbcIndexMeta idxMeta) { /** {@inheritDoc} */ @Override public ResultSet getSchemas(String catalog, String schemaPtrn) throws SQLException { - if (conn.isClosed()) - throw new SQLException("Connection is closed.", SqlStateCode.CONNECTION_CLOSED); + conn.ensureNotClosed(); final List meta = Arrays.asList( new JdbcColumnMeta(null, null, "TABLE_SCHEM", String.class), diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java index 2459aadcbdaaf..ae5417455026e 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -139,7 +139,7 @@ protected void execute0(JdbcStatementType stmtType, String sql, List arg int res = getUpdateCount(); if (res == -1) - throw new SQLException("The query is not DML statememt: " + sql, SqlStateCode.PARSING_EXCEPTION); + throw new SQLException("The query is not DML statement: " + sql, SqlStateCode.PARSING_EXCEPTION); return res; } @@ -563,6 +563,6 @@ JdbcThinConnection connection() { */ protected void ensureNotClosed() throws SQLException { if (isClosed()) - throw new SQLException("Statement is closed.", SqlStateCode.CONNECTION_CLOSED); + throw new SQLException("Statement is closed."); } } From 8e1e57437f1615b9f7f531e2a1092837e6e3e131 Mon Sep 17 00:00:00 2001 From: Alexander Paschenko Date: Fri, 15 Sep 2017 19:03:49 +0300 Subject: [PATCH 42/43] Test fix --- .../internal/processors/query/h2/sql/GridSqlQueryParser.java | 2 +- .../internal/processors/query/h2/sql/GridQueryParsingTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java index 6e27f9b08f458..3046c204be16b 100644 --- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java +++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/sql/GridSqlQueryParser.java @@ -941,7 +941,7 @@ private GridSqlCreateTable parseCreateTable(CreateTable createTbl) { int valColsNum = cols.size() - pkCols.size(); if (valColsNum == 0) - throw new IgniteSQLException("Table must have at least one non PRIMARY KEY columnn.", + throw new IgniteSQLException("Table must have at least one non PRIMARY KEY column.", IgniteQueryErrorCode.UNSUPPORTED_OPERATION); res.columns(cols); diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java index ca66bc1be0636..61694dd848812 100644 --- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java +++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/query/h2/sql/GridQueryParsingTest.java @@ -596,7 +596,7 @@ false, c("id", Value.INT), c("city", Value.STRING), c("name", Value.STRING), IgniteSQLException.class, "CREATE TABLE ... AS ... syntax is not supported"); assertParseThrows("create table Person (id int primary key)", - IgniteSQLException.class, "Tables with only key related columns are not supported at the moment"); + IgniteSQLException.class, "Table must have at least one non PRIMARY KEY column."); assertParseThrows("create table Person (id int primary key, age int unique) WITH \"template=cache\"", IgniteSQLException.class, "Too many constraints - only PRIMARY KEY is supported for CREATE TABLE"); From f67dc1a2c600607d4ca36580d191e1ff4136ebf0 Mon Sep 17 00:00:00 2001 From: devozerov Date: Sat, 16 Sep 2017 15:15:49 +0300 Subject: [PATCH 43/43] Merge w/ master. --- .../apache/ignite/internal/jdbc/thin/JdbcThinConnection.java | 4 ++-- .../org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java | 4 ---- .../internal/processors/odbc/jdbc/JdbcRequestHandler.java | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java index a8faf6b6221ee..511eba0152dc2 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.java @@ -38,7 +38,7 @@ import java.util.concurrent.Executor; import java.util.logging.Logger; import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; -import org.apache.ignite.internal.processors.odbc.SqlListenerResponse; +import org.apache.ignite.internal.processors.odbc.ClientListenerResponse; import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcResponse; @@ -664,7 +664,7 @@ R sendRequest(JdbcRequest req) throws SQLException { try { JdbcResponse res = cliIo.sendRequest(req); - if (res.status() != SqlListenerResponse.STATUS_SUCCESS) + if (res.status() != ClientListenerResponse.STATUS_SUCCESS) throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status())); return (R)res.response(); diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java index 3cf08c9e17ae8..70cf00e0599ae 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinTcpIo.java @@ -31,10 +31,6 @@ import org.apache.ignite.internal.processors.odbc.ClientListenerNioListener; import org.apache.ignite.internal.processors.odbc.ClientListenerProtocolVersion; import org.apache.ignite.internal.processors.odbc.ClientListenerRequest; -import org.apache.ignite.internal.processors.odbc.ClientListenerResponse; -import org.apache.ignite.internal.processors.odbc.SqlListenerNioListener; -import org.apache.ignite.internal.processors.odbc.SqlListenerProtocolVersion; -import org.apache.ignite.internal.processors.odbc.SqlListenerRequest; import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcBatchExecuteRequest; import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryCloseRequest; diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java index a94096322f964..fe50bb5b2a432 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/jdbc/JdbcRequestHandler.java @@ -188,7 +188,7 @@ public JdbcRequestHandler(GridKernalContext ctx, GridSpinBusyLock busyLock, int } /** {@inheritDoc} */ - @Override public SqlListenerResponse handleException(Exception e) { + @Override public ClientListenerResponse handleException(Exception e) { return exceptionToResult(e); }