IGNITE-6294: ODBC: implemented SQLSTATE management. This closes #2716.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/fc34091c Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/fc34091c Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/fc34091c Branch: refs/heads/ignite-2.1.5-p1 Commit: fc34091c750cdaf759a54a989a84c76f8d9f9f7f Parents: 49a3631 Author: Igor Sapego <[email protected]> Authored: Thu Sep 21 20:02:33 2017 +0300 Committer: devozerov <[email protected]> Committed: Thu Sep 21 20:05:40 2017 +0300 ---------------------------------------------------------------------- .../odbc/odbc/OdbcConnectionContext.java | 6 +- .../processors/odbc/odbc/OdbcMessageParser.java | 17 +- .../odbc/odbc/OdbcQueryExecuteBatchResult.java | 16 +- .../odbc/odbc/OdbcRequestHandler.java | 54 +++- .../processors/odbc/odbc/OdbcUtils.java | 24 +- modules/platforms/cpp/odbc-test/Makefile.am | 1 + .../cpp/odbc-test/project/vs/odbc-test.vcxproj | 1 + .../project/vs/odbc-test.vcxproj.filters | 3 + .../platforms/cpp/odbc-test/src/errors_test.cpp | 289 +++++++++++++++++++ .../platforms/cpp/odbc-test/src/parser_test.cpp | 4 +- .../cpp/odbc-test/src/queries_test.cpp | 16 +- modules/platforms/cpp/odbc/include/Makefile.am | 1 + .../cpp/odbc/include/ignite/odbc/common_types.h | 131 ++++++++- .../ignite/odbc/diagnostic/diagnosable.h | 9 + .../odbc/diagnostic/diagnosable_adapter.h | 8 + .../cpp/odbc/include/ignite/odbc/message.h | 48 +-- .../cpp/odbc/include/ignite/odbc/odbc_error.h | 94 ++++++ .../cpp/odbc/include/ignite/odbc/parser.h | 35 ++- .../platforms/cpp/odbc/project/vs/odbc.vcxproj | 1 + .../cpp/odbc/project/vs/odbc.vcxproj.filters | 3 + modules/platforms/cpp/odbc/src/common_types.cpp | 51 ++++ modules/platforms/cpp/odbc/src/connection.cpp | 25 +- .../odbc/src/diagnostic/diagnosable_adapter.cpp | 8 + .../odbc/src/diagnostic/diagnostic_record.cpp | 105 ++++++- modules/platforms/cpp/odbc/src/message.cpp | 37 ++- .../cpp/odbc/src/query/batch_query.cpp | 13 +- .../odbc/src/query/column_metadata_query.cpp | 11 +- .../platforms/cpp/odbc/src/query/data_query.cpp | 31 +- .../cpp/odbc/src/query/table_metadata_query.cpp | 11 +- modules/platforms/cpp/odbc/src/statement.cpp | 11 +- 30 files changed, 960 insertions(+), 104 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java index f2450e2..a4af478 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcConnectionContext.java @@ -32,10 +32,10 @@ import org.apache.ignite.internal.util.GridSpinBusyLock; */ public class OdbcConnectionContext implements ClientListenerConnectionContext { /** Version 2.1.0. */ - private static final ClientListenerProtocolVersion VER_2_1_0 = ClientListenerProtocolVersion.create(2, 1, 0); + public static final ClientListenerProtocolVersion VER_2_1_0 = ClientListenerProtocolVersion.create(2, 1, 0); /** Version 2.1.5: added "lazy" flag. */ - private static final ClientListenerProtocolVersion VER_2_1_5 = ClientListenerProtocolVersion.create(2, 1, 5); + public static final ClientListenerProtocolVersion VER_2_1_5 = ClientListenerProtocolVersion.create(2, 1, 5); /** Current version. */ private static final ClientListenerProtocolVersion CURRENT_VER = VER_2_1_5; @@ -101,7 +101,7 @@ public class OdbcConnectionContext implements ClientListenerConnectionContext { handler = new OdbcRequestHandler(ctx, busyLock, maxCursors, distributedJoins, enforceJoinOrder, replicatedOnly, collocated, lazy); - parser = new OdbcMessageParser(ctx); + parser = new OdbcMessageParser(ctx, ver); } /** {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java index 2ab7cee..04e2e25 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcMessageParser.java @@ -30,6 +30,7 @@ import org.apache.ignite.internal.binary.streams.BinaryHeapOutputStream; import org.apache.ignite.internal.binary.streams.BinaryInputStream; import org.apache.ignite.internal.processors.cache.binary.CacheObjectBinaryProcessorImpl; import org.apache.ignite.internal.processors.odbc.ClientListenerMessageParser; +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.SqlListenerUtils; @@ -51,11 +52,16 @@ public class OdbcMessageParser implements ClientListenerMessageParser { /** Logger. */ private final IgniteLogger log; + /** Protocol version */ + private final ClientListenerProtocolVersion ver; + /** * @param ctx Context. + * @param ver Protocol version. */ - public OdbcMessageParser(GridKernalContext ctx) { + public OdbcMessageParser(GridKernalContext ctx, ClientListenerProtocolVersion ver) { this.ctx = ctx; + this.ver = ver; log = ctx.log(getClass()); @@ -194,7 +200,11 @@ public class OdbcMessageParser implements ClientListenerMessageParser { BinaryThreadLocalContext.get().schemaHolder(), null); // Writing status. - writer.writeByte((byte) msg.status()); + if (ver.compareTo(OdbcConnectionContext.VER_2_1_5) < 0) { + writer.writeByte((byte) (msg.status() == ClientListenerResponse.STATUS_SUCCESS ? + ClientListenerResponse.STATUS_SUCCESS : ClientListenerResponse.STATUS_FAILED)); + } else + writer.writeInt(msg.status()); if (msg.status() != ClientListenerResponse.STATUS_SUCCESS) { writer.writeString(msg.error()); @@ -234,6 +244,9 @@ public class OdbcMessageParser implements ClientListenerMessageParser { if (res.errorMessage() != null) { writer.writeLong(res.errorSetIdx()); writer.writeString(res.errorMessage()); + + if (ver.compareTo(OdbcConnectionContext.VER_2_1_5) >= 0) + writer.writeInt(res.errorCode()); } } else if (res0 instanceof OdbcQueryFetchResult) { http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java index ee02fd6..c8f61dc 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcQueryExecuteBatchResult.java @@ -17,6 +17,7 @@ package org.apache.ignite.internal.processors.odbc.odbc; +import org.apache.ignite.internal.processors.odbc.ClientListenerResponse; import org.jetbrains.annotations.Nullable; /** @@ -29,6 +30,9 @@ public class OdbcQueryExecuteBatchResult { /** Index of the set which caused an error. */ private final long errorSetIdx; + /** Error code. */ + private final int errorCode; + /** Error message. */ private final String errorMessage; @@ -39,17 +43,20 @@ public class OdbcQueryExecuteBatchResult { this.rowsAffected = rowsAffected; this.errorSetIdx = -1; this.errorMessage = null; + this.errorCode = ClientListenerResponse.STATUS_SUCCESS; } /** * @param rowsAffected Number of rows affected by the query. * @param errorSetIdx Sets processed. + * @param errorCode Error code. * @param errorMessage Error message. */ - public OdbcQueryExecuteBatchResult(long rowsAffected, long errorSetIdx, String errorMessage) { + public OdbcQueryExecuteBatchResult(long rowsAffected, long errorSetIdx, int errorCode, String errorMessage) { this.rowsAffected = rowsAffected; this.errorSetIdx = errorSetIdx; this.errorMessage = errorMessage; + this.errorCode = errorCode; } /** @@ -72,4 +79,11 @@ public class OdbcQueryExecuteBatchResult { @Nullable public String errorMessage() { return errorMessage; } + + /** + * @return Error code. + */ + public int errorCode() { + return errorCode; + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java index fd31f39..07b41f3 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcRequestHandler.java @@ -35,6 +35,7 @@ import org.apache.ignite.internal.GridKernalContext; import org.apache.ignite.internal.binary.BinaryWriterExImpl; import org.apache.ignite.internal.binary.GridBinaryMarshaller; import org.apache.ignite.internal.processors.cache.QueryCursorImpl; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.ClientListenerRequest; import org.apache.ignite.internal.processors.odbc.ClientListenerRequestHandler; import org.apache.ignite.internal.processors.odbc.ClientListenerResponse; @@ -42,6 +43,7 @@ import org.apache.ignite.internal.processors.odbc.odbc.escape.OdbcEscapeUtils; import org.apache.ignite.internal.processors.query.GridQueryFieldMetadata; import org.apache.ignite.internal.processors.query.GridQueryIndexing; import org.apache.ignite.internal.processors.query.GridQueryTypeDescriptor; +import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.util.GridSpinBusyLock; import org.apache.ignite.internal.util.typedef.F; import org.apache.ignite.internal.util.typedef.internal.U; @@ -125,7 +127,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { OdbcRequest req = (OdbcRequest)req0; if (!busyLock.enterBusy()) - return new OdbcResponse(OdbcResponse.STATUS_FAILED, + return new OdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to handle ODBC request because node is stopping: " + req); try { @@ -152,7 +154,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { return getParamsMeta((OdbcQueryGetParamsMetaRequest)req); } - return new OdbcResponse(OdbcResponse.STATUS_FAILED, "Unsupported ODBC request: " + req); + return new OdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Unsupported ODBC request: " + req); } finally { busyLock.leaveBusy(); @@ -161,7 +163,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { /** {@inheritDoc} */ @Override public ClientListenerResponse handleException(Exception e, ClientListenerRequest req) { - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, e.toString()); + return exceptionToResult(e); } /** {@inheritDoc} */ @@ -219,7 +221,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { int cursorCnt = qryCursors.size(); if (maxCursors > 0 && cursorCnt >= maxCursors) - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, "Too many open cursors (either close " + + return new OdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Too many open cursors (either close " + "other open cursors or increase the limit through " + "ClientConnectorConfiguration.maxOpenCursorsPerConnection) [maximum=" + maxCursors + ", current=" + cursorCnt + ']'); @@ -258,7 +260,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -308,10 +310,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { catch (Exception e) { U.error(log, "Failed to execute SQL query [reqId=" + req.requestId() + ", req=" + req + ']', e); - OdbcQueryExecuteBatchResult res = new OdbcQueryExecuteBatchResult(rowsAffected, currentSet, - OdbcUtils.retrieveH2ErrorMessage(e)); - - return new OdbcResponse(res); + return exceptionToBatchResult(e, rowsAffected, currentSet); } } @@ -364,7 +363,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { IgniteBiTuple<QueryCursor, Iterator> tuple = qryCursors.get(queryId); if (tuple == null) - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, + return new OdbcResponse(IgniteQueryErrorCode.UNKNOWN, "Failed to find query with ID: " + queryId); CloseCursor(tuple, queryId); @@ -378,7 +377,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { U.error(log, "Failed to close SQL query [reqId=" + req.requestId() + ", req=" + queryId + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -427,7 +426,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { catch (Exception e) { U.error(log, "Failed to fetch SQL query result [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -492,7 +491,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { catch (Exception e) { U.error(log, "Failed to get columns metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -540,7 +539,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { catch (Exception e) { U.error(log, "Failed to get tables metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -571,7 +570,7 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { catch (Exception e) { U.error(log, "Failed to get params metadata [reqId=" + req.requestId() + ", req=" + req + ']', e); - return new OdbcResponse(ClientListenerResponse.STATUS_FAILED, OdbcUtils.retrieveH2ErrorMessage(e)); + return exceptionToResult(e); } } @@ -681,4 +680,29 @@ public class OdbcRequestHandler implements ClientListenerRequestHandler { return str != null && (F.isEmpty(ptrn) || str.toUpperCase().matches(ptrn.toUpperCase().replace("%", ".*").replace("_", "."))); } + + /** + * Create {@link OdbcResponse} bearing appropriate Ignite specific result code if possible + * from given {@link Exception}. + * + * @param e Exception to convert. + * @return resulting {@link OdbcResponse}. + */ + private OdbcResponse exceptionToBatchResult(Exception e, long rowsAffected, long currentSet) { + OdbcQueryExecuteBatchResult res = new OdbcQueryExecuteBatchResult(rowsAffected, currentSet, + OdbcUtils.tryRetrieveSqlErrorCode(e), OdbcUtils.tryRetrieveH2ErrorMessage(e)); + + return new OdbcResponse(res); + } + + /** + * Create {@link OdbcResponse} bearing appropriate Ignite specific result code if possible + * from given {@link Exception}. + * + * @param e Exception to convert. + * @return resulting {@link OdbcResponse}. + */ + private OdbcResponse exceptionToResult(Exception e) { + return new OdbcResponse(OdbcUtils.tryRetrieveSqlErrorCode(e), OdbcUtils.tryRetrieveH2ErrorMessage(e)); + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java index 3578145..98fa045 100644 --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/odbc/OdbcUtils.java @@ -18,7 +18,9 @@ package org.apache.ignite.internal.processors.odbc.odbc; import org.apache.ignite.IgniteException; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.odbc.SqlListenerDataTypes; +import org.apache.ignite.internal.processors.query.IgniteSQLException; /** * Various ODBC utility methods. @@ -141,11 +143,29 @@ public class OdbcUtils { } /** - * Retrieves error message from exception. + * Tries to retrieve SQL error code of the exception. If the exception is not {@link IgniteSQLException} returns + * {@link IgniteQueryErrorCode#UNKNOWN}. + * + * @param err Error to retrieve code from. + * @return Error code. + */ + public static int tryRetrieveSqlErrorCode(Throwable err) { + int errorCode = IgniteQueryErrorCode.UNKNOWN; + + if (err instanceof IgniteSQLException) + errorCode = ((IgniteSQLException) err).statusCode(); + + return errorCode; + } + + /** + * Tries to retrieve H2 engine error message from exception. If the exception is not of type + * "org.h2.jdbc.JdbcSQLException" returns original error message. + * * @param err Exception. * @return Error message. */ - public static String retrieveH2ErrorMessage(Throwable err) { + public static String tryRetrieveH2ErrorMessage(Throwable err) { String msg = err.getMessage(); Throwable e = err.getCause(); http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/Makefile.am b/modules/platforms/cpp/odbc-test/Makefile.am index 69b62f9..5c335cf 100644 --- a/modules/platforms/cpp/odbc-test/Makefile.am +++ b/modules/platforms/cpp/odbc-test/Makefile.am @@ -79,6 +79,7 @@ ignite_odbc_tests_SOURCES = \ src/sql_outer_join_test.cpp \ src/api_robustness_test.cpp \ src/attributes_test.cpp \ + src/errors_test.cpp \ ../odbc/src/cursor.cpp \ ../odbc/src/config/connection_info.cpp \ ../odbc/src/app/application_data_buffer.cpp \ http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj index 3977a24..6ee999e 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj @@ -169,6 +169,7 @@ <ClCompile Include="..\..\src\configuration_test.cpp" /> <ClCompile Include="..\..\src\connection_info_test.cpp" /> <ClCompile Include="..\..\src\cursor_test.cpp" /> + <ClCompile Include="..\..\src\errors_test.cpp" /> <ClCompile Include="..\..\src\meta_queries_test.cpp" /> <ClCompile Include="..\..\src\queries_test.cpp" /> <ClCompile Include="..\..\src\parser_test.cpp" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters index 2a0c7b4..abfe303 100644 --- a/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters +++ b/modules/platforms/cpp/odbc-test/project/vs/odbc-test.vcxproj.filters @@ -127,6 +127,9 @@ <ClCompile Include="..\..\src\attributes_test.cpp"> <Filter>Code</Filter> </ClCompile> + <ClCompile Include="..\..\src\errors_test.cpp"> + <Filter>Code</Filter> + </ClCompile> </ItemGroup> <ItemGroup> <ClInclude Include="..\..\include\test_type.h"> http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/src/errors_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/errors_test.cpp b/modules/platforms/cpp/odbc-test/src/errors_test.cpp new file mode 100644 index 0000000..bac9fd4 --- /dev/null +++ b/modules/platforms/cpp/odbc-test/src/errors_test.cpp @@ -0,0 +1,289 @@ +/* + * 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. + */ + +#ifdef _WIN32 +# include <windows.h> +#endif + +#include <sql.h> +#include <sqlext.h> + +#include <vector> +#include <string> +#include <algorithm> + +#ifndef _MSC_VER +# define BOOST_TEST_DYN_LINK +#endif + +#include <boost/regex.hpp> +#include <boost/test/unit_test.hpp> + +#include "ignite/ignite.h" +#include "ignite/common/fixed_size_array.h" +#include "ignite/ignition.h" +#include "ignite/impl/binary/binary_utils.h" +#include "ignite/binary/binary_object.h" + +#include "test_type.h" +#include "complex_type.h" +#include "test_utils.h" + +using namespace ignite; +using namespace ignite::cache; +using namespace ignite::cache::query; +using namespace ignite::common; +using namespace ignite_test; +using namespace ignite::binary; +using namespace ignite::impl::binary; +using namespace ignite::impl::interop; + +using namespace boost::unit_test; + +using ignite::impl::binary::BinaryUtils; + +/** + * Test setup fixture. + */ +struct ErrorTestSuiteFixture +{ + /** + * Establish connection to node. + * + * @param connectStr Connection string. + */ + void Connect(const std::string& connectStr) + { + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + BOOST_REQUIRE(env != NULL); + + // We want ODBC 3 support + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0); + + // Allocate a connection handle + SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); + + BOOST_REQUIRE(dbc != NULL); + + // Connect string + std::vector<SQLCHAR> connectStr0; + + connectStr0.reserve(connectStr.size() + 1); + std::copy(connectStr.begin(), connectStr.end(), std::back_inserter(connectStr0)); + + SQLCHAR outstr[ODBC_BUFFER_SIZE]; + SQLSMALLINT outstrlen; + + // Connecting to ODBC server. + SQLRETURN ret = SQLDriverConnect(dbc, NULL, &connectStr0[0], static_cast<SQLSMALLINT>(connectStr0.size()), + outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); + + if (!SQL_SUCCEEDED(ret)) + { + Ignition::StopAll(true); + + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, dbc)); + } + + // Allocate a statement handle + SQLAllocHandle(SQL_HANDLE_STMT, dbc, &stmt); + + BOOST_REQUIRE(stmt != NULL); + } + + void Disconnect() + { + // Releasing statement handle. + SQLFreeHandle(SQL_HANDLE_STMT, stmt); + + // Disconneting from the server. + SQLDisconnect(dbc); + + // Releasing allocated handles. + SQLFreeHandle(SQL_HANDLE_DBC, dbc); + SQLFreeHandle(SQL_HANDLE_ENV, env); + } + + static Ignite StartAdditionalNode(const char* name) + { +#ifdef IGNITE_TESTS_32 + return StartNode("queries-test-32.xml", name); +#else + return StartNode("queries-test.xml", name); +#endif + } + + /** + * Constructor. + */ + ErrorTestSuiteFixture() : + env(NULL), + dbc(NULL), + stmt(NULL) + { + // No-op. + } + + /** + * Destructor. + */ + ~ErrorTestSuiteFixture() + { + Disconnect(); + + Ignition::StopAll(true); + } + + /** Frist cache instance. */ + //Cache<int64_t, TestType> cache; + + /** ODBC Environment. */ + SQLHENV env; + + /** ODBC Connect. */ + SQLHDBC dbc; + + /** ODBC Statement. */ + SQLHSTMT stmt; +}; + +BOOST_FIXTURE_TEST_SUITE(ErrorTestSuite, ErrorTestSuiteFixture) + +BOOST_AUTO_TEST_CASE(TestConnectFail) +{ + // Allocate an environment handle + SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &env); + + BOOST_REQUIRE(env != NULL); + + // We want ODBC 3 support + SQLSetEnvAttr(env, SQL_ATTR_ODBC_VERSION, reinterpret_cast<void*>(SQL_OV_ODBC3), 0); + + // Allocate a connection handle + SQLAllocHandle(SQL_HANDLE_DBC, env, &dbc); + + BOOST_REQUIRE(dbc != NULL); + + // Connect string + SQLCHAR connectStr[] = "DRIVER={Apache Ignite};ADDRESS=127.0.0.1:9999;SCHEMA=cache"; + + SQLCHAR outstr[ODBC_BUFFER_SIZE]; + SQLSMALLINT outstrlen; + + // Connecting to ODBC server. + SQLRETURN ret = SQLDriverConnect(dbc, NULL, connectStr, SQL_NTS, + outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_DBC, dbc), "08001"); +} + +BOOST_AUTO_TEST_CASE(TestDuplicateKey) +{ + StartAdditionalNode("Node1"); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); + + SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(1, 'some')"; + + SQLRETURN ret; + + ret = SQLExecDirect(stmt, insertReq, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + ret = SQLExecDirect(stmt, insertReq, SQL_NTS); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "23000"); +} + +BOOST_AUTO_TEST_CASE(TestUpdateKey) +{ + StartAdditionalNode("Node1"); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache"); + + SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(1, 'some')"; + + SQLRETURN ret; + + ret = SQLExecDirect(stmt, insertReq, SQL_NTS); + + if (!SQL_SUCCEEDED(ret)) + BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt)); + + SQLCHAR updateReq[] = "UPDATE TestType SET _key=2 WHERE _key=1"; + + ret = SQLExecDirect(stmt, updateReq, SQL_NTS); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "42000"); +} + +BOOST_AUTO_TEST_CASE(TestTableNotFound) +{ + StartAdditionalNode("Node1"); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=PUBLIC"); + + SQLCHAR req[] = "DROP TABLE Nonexisting"; + + SQLRETURN ret; + + ret = SQLExecDirect(stmt, req, SQL_NTS); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "42S02"); +} + +BOOST_AUTO_TEST_CASE(TestIndexNotFound) +{ + StartAdditionalNode("Node1"); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=PUBLIC"); + + SQLCHAR req[] = "DROP INDEX Nonexisting"; + + SQLRETURN ret; + + ret = SQLExecDirect(stmt, req, SQL_NTS); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "42S12"); +} + +BOOST_AUTO_TEST_CASE(TestSyntaxError) +{ + StartAdditionalNode("Node1"); + + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=PUBLIC"); + + SQLCHAR req[] = "INSERT INTO TestType(_key, fasf) VALUES(1, 'some')"; + + SQLRETURN ret; + + ret = SQLExecDirect(stmt, req, SQL_NTS); + + BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); + BOOST_CHECK_EQUAL(GetOdbcErrorState(SQL_HANDLE_STMT, stmt), "42000"); +} + +BOOST_AUTO_TEST_SUITE_END() http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/src/parser_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/parser_test.cpp b/modules/platforms/cpp/odbc-test/src/parser_test.cpp index 7c8a73d..51539ae 100644 --- a/modules/platforms/cpp/odbc-test/src/parser_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/parser_test.cpp @@ -27,7 +27,7 @@ using namespace ignite::odbc; struct TestMessage { - TestMessage() + TestMessage() : a(0), b() { // No-op. } @@ -48,7 +48,7 @@ struct TestMessage writer.WriteString(b.data(), static_cast<int32_t>(b.size())); } - void Read(ignite::impl::binary::BinaryReaderImpl& reader) + void Read(ignite::impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { a = reader.ReadInt32(); http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc-test/src/queries_test.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc-test/src/queries_test.cpp b/modules/platforms/cpp/odbc-test/src/queries_test.cpp index e7168fe..4c7e402 100644 --- a/modules/platforms/cpp/odbc-test/src/queries_test.cpp +++ b/modules/platforms/cpp/odbc-test/src/queries_test.cpp @@ -734,11 +734,25 @@ BOOST_FIXTURE_TEST_SUITE(QueriesTestSuite, QueriesTestSuiteFixture) BOOST_AUTO_TEST_CASE(TestLegacyConnection) { Connect("DRIVER={Apache Ignite};SERVER=127.0.0.1;PORT=11110;SCHEMA=cache"); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); } BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_0) { Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.0"); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); +} + +BOOST_AUTO_TEST_CASE(TestConnectionProtocolVersion_2_1_5) +{ + Connect("DRIVER={Apache Ignite};ADDRESS=127.0.0.1:11110;SCHEMA=cache;PROTOCOL_VERSION=2.1.5"); + + InsertTestStrings(10, false); + InsertTestBatch(11, 20, 9); } BOOST_AUTO_TEST_CASE(TestTwoRowsInt8) @@ -2119,7 +2133,7 @@ BOOST_AUTO_TEST_CASE(TestErrorMessage) BOOST_REQUIRE_EQUAL(ret, SQL_ERROR); std::string error = GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt); - std::string pattern = "HY000: Table \"B\" not found; SQL statement:\\vSELECT a FROM B.*"; + std::string pattern = "42000: Table \"B\" not found; SQL statement:\\vSELECT a FROM B.*"; boost::cmatch what; if (!boost::regex_match(error.c_str(), what, boost::regex(pattern))) http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/Makefile.am ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/Makefile.am b/modules/platforms/cpp/odbc/include/Makefile.am index 92c85c5..7c64754 100644 --- a/modules/platforms/cpp/odbc/include/Makefile.am +++ b/modules/platforms/cpp/odbc/include/Makefile.am @@ -51,6 +51,7 @@ noinst_HEADERS = \ ignite/odbc/diagnostic/diagnosable.h \ ignite/odbc/diagnostic/diagnosable_adapter.h \ ignite/odbc/connection.h \ + ignite/odbc/odbc_error.h \ ignite/odbc/message.h \ ignite/odbc/cursor.h \ ignite/odbc/common_types.h \ http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h index 0a3b02f..349147f 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h @@ -77,12 +77,42 @@ namespace ignite */ S01S02_OPTION_VALUE_CHANGED, + /** Restricted data type attribute violation. */ + S07006_RESTRICTION_VIOLATION, + /** String data, length mismatch. */ S22026_DATA_LENGTH_MISMATCH, + /** Integrity constraint violation. */ + S23000_INTEGRITY_CONSTRAINT_VIOLATION, + /** Invalid cursor state. */ S24000_INVALID_CURSOR_STATE, + /** Invalid schema name. */ + S3F000_INVALID_SCHEMA_NAME, + + /** Syntax error or access violation. */ + S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION, + + /** Base table or view already exists. */ + S42S01_TABLE_OR_VIEW_ALREADY_EXISTS, + + /** Base table or view not found. */ + S42S02_TABLE_OR_VIEW_NOT_FOUND, + + /** Index already exists. */ + S42S11_INDEX_ALREADY_EXISTS, + + /** Index not found. */ + S42S12_INDEX_NOT_FOUND, + + /** Column already exists. */ + S42S21_COLUMN_ALREADY_EXISTS, + + /** Column not found. */ + S42S22_COLUMN_NOT_FOUND, + /** Invalid descriptor index. */ S07009_INVALID_DESCRIPTOR_INDEX, @@ -102,6 +132,12 @@ namespace ignite /** The connection specified was not open. */ S08003_NOT_CONNECTED, + /** Server rejected the connection. */ + S08004_CONNECTION_REJECTED, + + /** Communication link failure. */ + S08S01_LINK_FAILURE, + /** * An error occurred for which there was no specific SQLSTATE * and for which no implementation-specific SQLSTATE was defined. @@ -120,6 +156,9 @@ namespace ignite */ SHY003_INVALID_APPLICATION_BUFFER_TYPE, + /** Invalid SQL data type. */ + SHY004_INVALID_SQL_DATA_TYPE, + /** Invalid use of null pointer. */ SHY009_INVALID_USE_OF_NULL_POINTER, @@ -155,7 +194,7 @@ namespace ignite * The connection timeout period expired before the data source * responded to the request. */ - SHYT01_CONNECTIOIN_TIMEOUT, + SHYT01_CONNECTION_TIMEOUT, /** * Driver does not support this function. @@ -245,6 +284,88 @@ namespace ignite }; }; + struct ResponseStatus + { + enum Type + { + /** Operation completed successfully. */ + SUCCESS = 0, + + /* 1xxx - parsing errors */ + + /** Unknown error, or the one without specific code. */ + UNKNOWN_ERROR = 1, + + /** General parsing error - for the cases when there's no more specific code available. */ + PARSING_FAILURE = 1001, + + /** Requested operation is not supported. */ + UNSUPPORTED_OPERATION = 1002, + + /* 2xxx - analysis errors */ + + /** Code encountered SQL statement of some type that it did not expect in current analysis context. */ + UNEXPECTED_OPERATION = 2001, + + /** Code encountered SQL expression of some type that it did not expect in current analysis context. */ + UNEXPECTED_ELEMENT_TYPE = 2002, + + /** Analysis detected that the statement is trying to directly UPDATE key or its fields. */ + KEY_UPDATE = 2003, + + /* 3xxx - database API related runtime errors */ + /** Required table not found. */ + TABLE_NOT_FOUND = 3001, + + /** Required table does not have a descriptor set. */ + NULL_TABLE_DESCRIPTOR = 3002, + + /** Statement type does not match that declared by JDBC driver. */ + STMT_TYPE_MISMATCH = 3003, + + /** DROP TABLE failed. */ + TABLE_DROP_FAILED = 3004, + + /** Index already exists. */ + INDEX_ALREADY_EXISTS = 3005, + + /** Index does not exist. */ + INDEX_NOT_FOUND = 3006, + + /** Required table already exists. */ + TABLE_ALREADY_EXISTS = 3007, + + /** Required column not found. */ + COLUMN_NOT_FOUND = 3008, + + /** Required column already exists. */ + COLUMN_ALREADY_EXISTS = 3009, + + /** Conversion failure. */ + CONVERSION_FAILED = 3013, + + /* 4xxx - cache related runtime errors */ + + /** Attempt to INSERT a key that is already in cache. */ + DUPLICATE_KEY = 4001, + + /** Attempt to UPDATE or DELETE a key whose value has been updated concurrently by someone else. */ + CONCURRENT_UPDATE = 4002, + + /** Attempt to INSERT or MERGE {@code null} key. */ + NULL_KEY = 4003, + + /** Attempt to INSERT or MERGE {@code null} value. */ + NULL_VALUE = 4004, + + /** EntryProcessor has thrown an exception during IgniteCache::invokeAll. */ + ENTRY_PROCESSING = 4005, + + /** Cache not found. */ + CACHE_NOT_FOUND = 4006 + }; + }; + /** * Convert internal Ignite type into ODBC SQL return code. * @@ -269,7 +390,13 @@ namespace ignite */ EnvironmentAttribute::Type EnvironmentAttributeToInternal(int32_t attr); - + /** + * Convert request response status to SQL state. + * + * @param status Response status. + * @return SQL state. + */ + SqlState::Type ResponseStatusToSqlState(int32_t status); } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h index 2ec1b5b..46d79ce 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable.h @@ -24,6 +24,8 @@ namespace ignite { namespace odbc { + class OdbcError; + namespace diagnostic { /** @@ -73,6 +75,13 @@ namespace ignite */ virtual void AddStatusRecord(SqlState::Type sqlState, const std::string& message) = 0; + /** + * Add new status record. + * + * @param err Error. + */ + virtual void AddStatusRecord(const OdbcError& err) = 0; + protected: /** * Default constructor. http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h index 45f47f0..461bfc9 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/diagnostic/diagnosable_adapter.h @@ -33,6 +33,7 @@ namespace ignite { namespace odbc { + class OdbcError; class Connection; namespace diagnostic @@ -90,6 +91,13 @@ namespace ignite */ virtual void AddStatusRecord(SqlState::Type sqlState, const std::string& message); + /** + * Add new status record. + * + * @param err Error. + */ + virtual void AddStatusRecord(const OdbcError& err); + protected: /** * Constructor. http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/message.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h index fd7897f..91a808c 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/message.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/message.h @@ -64,16 +64,6 @@ namespace ignite }; }; - struct ResponseStatus - { - enum Type - { - SUCCESS = 0, - - FAILED = 1 - }; - }; - /** * Handshake request. */ @@ -411,14 +401,15 @@ namespace ignite /** * Read response using provided reader. * @param reader Reader. + * @param ver Protocol version. */ - void Read(impl::binary::BinaryReaderImpl& reader); + void Read(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion& ver); /** * Get request processing status. * @return Status. */ - int8_t GetStatus() const + int32_t GetStatus() const { return status; } @@ -436,11 +427,11 @@ namespace ignite /** * Read data if response status is ResponseStatus::SUCCESS. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl&); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl&, const ProtocolVersion&); private: /** Request processing status. */ - int8_t status; + int32_t status; /** Error message. */ std::string error; @@ -493,7 +484,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - void Read(impl::binary::BinaryReaderImpl& reader); + void Read(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); private: /** Handshake accepted. */ @@ -536,7 +527,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Query ID. */ int64_t queryId; @@ -590,7 +581,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Query ID. */ int64_t queryId; @@ -645,12 +636,22 @@ namespace ignite return errorMessage; } + /** + * Get error code. + * @return Error code. + */ + int32_t GetErrorCode() const + { + return errorCode; + } + private: /** * Read response using provided reader. * @param reader Reader. + * @param ver Protocol version. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion& ver); /** Affected rows. */ int64_t affectedRows; @@ -660,6 +661,9 @@ namespace ignite /** Error message. */ std::string errorMessage; + + /** Error code. */ + int32_t errorCode; }; /** @@ -693,7 +697,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Query ID. */ int64_t queryId; @@ -732,7 +736,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Columns metadata. */ meta::ColumnMetaVector meta; @@ -768,7 +772,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Columns metadata. */ meta::TableMetaVector meta; @@ -804,7 +808,7 @@ namespace ignite * Read response using provided reader. * @param reader Reader. */ - virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader); + virtual void ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&); /** Columns metadata. */ std::vector<int8_t> typeIds; http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/odbc_error.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/odbc_error.h b/modules/platforms/cpp/odbc/include/ignite/odbc/odbc_error.h new file mode 100644 index 0000000..361b2b5 --- /dev/null +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/odbc_error.h @@ -0,0 +1,94 @@ +/* + * 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. + */ + +#ifndef _IGNITE_ODBC_ODBC_ERROR +#define _IGNITE_ODBC_ODBC_ERROR + +#include <string> + +#include "ignite/odbc/common_types.h" + +namespace ignite +{ + namespace odbc + { + /** + * ODBC error. + */ + class OdbcError + { + public: + /** + * Constructor. + * + * @param status SQL status. + * @param message Error message. + */ + OdbcError(SqlState::Type status, const std::string& message) : + status(status), + errMessage(message) + { + // No-op. + } + + /** + * Default constructor. + */ + OdbcError() : + status(SqlState::UNKNOWN), + errMessage() + { + // No-op. + } + + /** + * Destructor. + */ + ~OdbcError() + { + // No-op. + } + + /** + * Get status. + * @return Status. + */ + SqlState::Type GetStatus() const + { + return status; + } + + /** + * Get error message. + * @return Error message. + */ + const std::string& GetErrorMessage() const + { + return errMessage; + } + + private: + /** Status. */ + SqlState::Type status; + + /** Error message. */ + std::string errMessage; + }; + } +} + +#endif //_IGNITE_ODBC_ODBC_ERROR \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h index a91af22..bfea67c 100644 --- a/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h +++ b/modules/platforms/cpp/odbc/include/ignite/odbc/parser.h @@ -28,6 +28,7 @@ #include <ignite/impl/binary/binary_reader_impl.h> #include "ignite/odbc/utility.h" +#include "ignite/odbc/protocol_version.h" namespace ignite { @@ -44,8 +45,13 @@ namespace ignite /** * Constructor. + * @param cap Initial capasity. */ - Parser(int32_t cap = DEFAULT_MEM_ALLOCATION) : inMem(cap), outMem(cap), outStream(&outMem) + Parser(int32_t cap = DEFAULT_MEM_ALLOCATION) : + protocolVer(ProtocolVersion::GetCurrent()), + inMem(cap), + outMem(cap), + outStream(&outMem) { //No-op. } @@ -67,7 +73,7 @@ namespace ignite template<typename MsgT> void Encode(const MsgT& msg, std::vector<int8_t>& buf) { - using namespace ignite::impl::binary; + using namespace impl::binary; ResetState(); @@ -90,7 +96,7 @@ namespace ignite template<typename MsgT> void Decode(MsgT& msg, const std::vector<int8_t>& buf) { - using namespace ignite::impl::binary; + using namespace impl::binary; if (inMem.Capacity() < static_cast<int32_t>(buf.size())) inMem.Reallocate(static_cast<int32_t>(buf.size())); @@ -99,11 +105,21 @@ namespace ignite inMem.Length(static_cast<int32_t>(buf.size())); - ignite::impl::interop::InteropInputStream inStream(&inMem); + impl::interop::InteropInputStream inStream(&inMem); BinaryReaderImpl reader(&inStream); - msg.Read(reader); + msg.Read(reader, protocolVer); + } + + /** + * Set protocol version. + * + * @param ver Version to set. + */ + void SetProtocolVersion(const ProtocolVersion& ver) + { + protocolVer = ver; } private: @@ -119,14 +135,17 @@ namespace ignite outStream.Position(0); } + /** Protocol version. */ + ProtocolVersion protocolVer; + /** Input operational memory. */ - ignite::impl::interop::InteropUnpooledMemory inMem; + impl::interop::InteropUnpooledMemory inMem; /** Output operational memory. */ - ignite::impl::interop::InteropUnpooledMemory outMem; + impl::interop::InteropUnpooledMemory outMem; /** Output stream. */ - ignite::impl::interop::InteropOutputStream outStream; + impl::interop::InteropOutputStream outStream; }; } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj index e47f618..c5783ff 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj @@ -217,6 +217,7 @@ <ClInclude Include="..\..\include\ignite\odbc\meta\column_meta.h" /> <ClInclude Include="..\..\include\ignite\odbc\meta\primary_key_meta.h" /> <ClInclude Include="..\..\include\ignite\odbc\meta\table_meta.h" /> + <ClInclude Include="..\..\include\ignite\odbc\odbc_error.h" /> <ClInclude Include="..\..\include\ignite\odbc\parser.h" /> <ClInclude Include="..\..\include\ignite\odbc\protocol_version.h" /> <ClInclude Include="..\..\include\ignite\odbc\query\batch_query.h" /> http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters index e252d5d..8934625 100644 --- a/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters +++ b/modules/platforms/cpp/odbc/project/vs/odbc.vcxproj.filters @@ -281,5 +281,8 @@ <ClInclude Include="..\..\include\ignite\odbc\query\batch_query.h"> <Filter>Code\query</Filter> </ClInclude> + <ClInclude Include="..\..\include\ignite\odbc\odbc_error.h"> + <Filter>Code</Filter> + </ClInclude> </ItemGroup> </Project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/common_types.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/common_types.cpp b/modules/platforms/cpp/odbc/src/common_types.cpp index 09ea3dc..10c4f77 100644 --- a/modules/platforms/cpp/odbc/src/common_types.cpp +++ b/modules/platforms/cpp/odbc/src/common_types.cpp @@ -118,6 +118,57 @@ namespace ignite return EnvironmentAttribute::UNKNOWN; } + + SqlState::Type ResponseStatusToSqlState(int32_t status) + { + switch (status) + { + case ResponseStatus::PARSING_FAILURE: + case ResponseStatus::KEY_UPDATE: + case ResponseStatus::UNEXPECTED_OPERATION: + return SqlState::S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION; + + case ResponseStatus::UNSUPPORTED_OPERATION: + return SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED; + + case ResponseStatus::UNEXPECTED_ELEMENT_TYPE: + return SqlState::SHY004_INVALID_SQL_DATA_TYPE; + + case ResponseStatus::DUPLICATE_KEY: + case ResponseStatus::NULL_KEY: + case ResponseStatus::NULL_VALUE: + return SqlState::S23000_INTEGRITY_CONSTRAINT_VIOLATION; + + case ResponseStatus::TABLE_NOT_FOUND: + return SqlState::S42S02_TABLE_OR_VIEW_NOT_FOUND; + + case ResponseStatus::INDEX_ALREADY_EXISTS: + return SqlState::S42S11_INDEX_ALREADY_EXISTS; + + case ResponseStatus::INDEX_NOT_FOUND: + return SqlState::S42S12_INDEX_NOT_FOUND; + + case ResponseStatus::TABLE_ALREADY_EXISTS: + return SqlState::S42S01_TABLE_OR_VIEW_ALREADY_EXISTS; + + case ResponseStatus::COLUMN_NOT_FOUND: + return SqlState::S42S22_COLUMN_NOT_FOUND; + + case ResponseStatus::COLUMN_ALREADY_EXISTS: + return SqlState::S42S21_COLUMN_ALREADY_EXISTS; + + case ResponseStatus::CACHE_NOT_FOUND: + case ResponseStatus::NULL_TABLE_DESCRIPTOR: + case ResponseStatus::CONVERSION_FAILED: + case ResponseStatus::CONCURRENT_UPDATE: + case ResponseStatus::ENTRY_PROCESSING: + case ResponseStatus::TABLE_DROP_FAILED: + case ResponseStatus::STMT_TYPE_MISMATCH: + case ResponseStatus::UNKNOWN_ERROR: + default: + return SqlState::SHY000_GENERAL_ERROR; + } + } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/connection.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/connection.cpp b/modules/platforms/cpp/odbc/src/connection.cpp index 777973a..161e1c4 100644 --- a/modules/platforms/cpp/odbc/src/connection.cpp +++ b/modules/platforms/cpp/odbc/src/connection.cpp @@ -27,6 +27,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/config/configuration.h" +#include "ignite/odbc/odbc_error.h" namespace { @@ -138,6 +139,8 @@ namespace ignite if (res == SqlResult::AI_ERROR) Close(); + else + parser.SetProtocolVersion(config.GetProtocolVersion()); return res; } @@ -194,7 +197,7 @@ namespace ignite void Connection::Send(const int8_t* data, size_t len) { if (!connected) - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_ILLEGAL_STATE, "Connection is not established"); + throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); int32_t newLen = static_cast<int32_t>(len + sizeof(OdbcProtocolHeader)); @@ -209,7 +212,7 @@ namespace ignite size_t sent = SendAll(msg.GetData(), msg.GetSize()); if (sent != len + sizeof(OdbcProtocolHeader)) - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not send message"); + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not send message due to connection failure"); LOG_MSG("message sent: (" << msg.GetSize() << " bytes)" << utility::HexDump(msg.GetData(), msg.GetSize())); } @@ -240,7 +243,7 @@ namespace ignite void Connection::Receive(std::vector<int8_t>& msg) { if (!connected) - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_ILLEGAL_STATE, "Connection is not established"); + throw OdbcError(SqlState::S08003_NOT_CONNECTED, "Connection is not established"); msg.clear(); @@ -249,13 +252,13 @@ namespace ignite size_t received = ReceiveAll(reinterpret_cast<int8_t*>(&hdr), sizeof(hdr)); if (received != sizeof(hdr)) - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not receive message header"); + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message header"); if (hdr.len < 0) { Close(); - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Message length is negative"); + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Protocol error: Message length is negative"); } if (hdr.len == 0) @@ -269,7 +272,7 @@ namespace ignite { msg.resize(received); - IGNITE_ERROR_1(IgniteError::IGNITE_ERR_GENERIC, "Can not receive message body"); + throw OdbcError(SqlState::S08S01_LINK_FAILURE, "Can not receive message body"); } LOG_MSG("Message received: " << utility::HexDump(&msg[0], msg.size())); @@ -447,9 +450,15 @@ namespace ignite { SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, err.GetText()); return SqlResult::AI_ERROR; } @@ -469,7 +478,7 @@ namespace ignite << "driver protocol version introduced in version: " << config.GetProtocolVersion().ToString() << "."; - AddStatusRecord(SqlState::S08001_CANNOT_CONNECT, constructor.str()); + AddStatusRecord(SqlState::S08004_CONNECTION_REJECTED, constructor.str()); return SqlResult::AI_ERROR; } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp index 6c07c29..096593f 100644 --- a/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnosable_adapter.cpp @@ -17,6 +17,7 @@ #include "ignite/odbc/log.h" #include "ignite/odbc/connection.h" +#include "ignite/odbc/odbc_error.h" #include "ignite/odbc/diagnostic/diagnosable_adapter.h" namespace ignite @@ -46,6 +47,13 @@ namespace ignite AddStatusRecord(sqlState, message, 0, 0); } + + void DiagnosableAdapter::AddStatusRecord(const OdbcError& err) + { + LOG_MSG("Adding new record: " << err.GetErrorMessage()); + + AddStatusRecord(err.GetStatus(), err.GetErrorMessage(), 0, 0); + } } } } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp index c8e0e81..0a02310 100644 --- a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp +++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp @@ -40,15 +40,15 @@ namespace /** SQL state 01S01 constant. */ const std::string STATE_01S01 = "01S01"; - /** SQL state 22026 constant. */ - const std::string STATE_22026 = "22026"; - - /** SQL state 24000 constant. */ - const std::string STATE_24000 = "24000"; + /** SQL state 01S02 constant. */ + const std::string STATE_01S02 = "01S02"; /** SQL state 07009 constant. */ const std::string STATE_07009 = "07009"; + /** SQL state 07006 constant. */ + const std::string STATE_07006 = "07006"; + /** SQL state 08001 constant. */ const std::string STATE_08001 = "08001"; @@ -58,6 +58,45 @@ namespace /** SQL state 08003 constant. */ const std::string STATE_08003 = "08003"; + /** SQL state 08004 constant. */ + const std::string STATE_08004 = "08004"; + + /** SQL state 08S01 constant. */ + const std::string STATE_08S01 = "08S01"; + + /** SQL state 22026 constant. */ + const std::string STATE_22026 = "22026"; + + /** SQL state 23000 constant. */ + const std::string STATE_23000 = "23000"; + + /** SQL state 24000 constant. */ + const std::string STATE_24000 = "24000"; + + /** SQL state 3F000 constant. */ + const std::string STATE_3F000 = "3F000"; + + /** SQL state 42000 constant. */ + const std::string STATE_42000 = "42000"; + + /** SQL state 42S01 constant. */ + const std::string STATE_42S01 = "42S01"; + + /** SQL state 42S02 constant. */ + const std::string STATE_42S02 = "42S02"; + + /** SQL state 42S11 constant. */ + const std::string STATE_42S11 = "42S11"; + + /** SQL state 42S12 constant. */ + const std::string STATE_42S12 = "42S12"; + + /** SQL state 42S21 constant. */ + const std::string STATE_42S21 = "42S21"; + + /** SQL state 42S22 constant. */ + const std::string STATE_42S22 = "42S22"; + /** SQL state HY000 constant. */ const std::string STATE_HY000 = "HY000"; @@ -67,15 +106,24 @@ namespace /** SQL state HY003 constant. */ const std::string STATE_HY003 = "HY003"; + /** SQL state HY004 constant. */ + const std::string STATE_HY004 = "HY004"; + /** SQL state HY009 constant. */ const std::string STATE_HY009 = "HY009"; /** SQL state HY010 constant. */ const std::string STATE_HY010 = "HY010"; + /** SQL state HY090 constant. */ + const std::string STATE_HY090 = "HY090"; + /** SQL state HY092 constant. */ const std::string STATE_HY092 = "HY092"; + /** SQL state HY097 constant. */ + const std::string STATE_HY097 = "HY097"; + /** SQL state HY105 constant. */ const std::string STATE_HY105 = "HY105"; @@ -88,9 +136,6 @@ namespace /** SQL state HYT01 constant. */ const std::string STATE_HYT01 = "HYT01"; - /** SQL state HY090 constant. */ - const std::string STATE_HY090 = "HY090"; - /** SQL state IM001 constant. */ const std::string STATE_IM001 = "IM001"; } @@ -230,12 +275,45 @@ namespace ignite case SqlState::S01S01_ERROR_IN_ROW: return STATE_01S01; + case SqlState::S01S02_OPTION_VALUE_CHANGED: + return STATE_01S02; + + case SqlState::S07006_RESTRICTION_VIOLATION: + return STATE_07006; + case SqlState::S22026_DATA_LENGTH_MISMATCH: return STATE_22026; + case SqlState::S23000_INTEGRITY_CONSTRAINT_VIOLATION: + return STATE_23000; + case SqlState::S24000_INVALID_CURSOR_STATE: return STATE_24000; + case SqlState::S3F000_INVALID_SCHEMA_NAME: + return STATE_3F000; + + case SqlState::S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION: + return STATE_42000; + + case SqlState::S42S01_TABLE_OR_VIEW_ALREADY_EXISTS: + return STATE_42S01; + + case SqlState::S42S02_TABLE_OR_VIEW_NOT_FOUND: + return STATE_42S02; + + case SqlState::S42S11_INDEX_ALREADY_EXISTS: + return STATE_42S11; + + case SqlState::S42S12_INDEX_NOT_FOUND: + return STATE_42S12; + + case SqlState::S42S21_COLUMN_ALREADY_EXISTS: + return STATE_42S21; + + case SqlState::S42S22_COLUMN_NOT_FOUND: + return STATE_42S22; + case SqlState::S07009_INVALID_DESCRIPTOR_INDEX: return STATE_07009; @@ -248,6 +326,12 @@ namespace ignite case SqlState::S08003_NOT_CONNECTED: return STATE_08003; + case SqlState::S08004_CONNECTION_REJECTED: + return STATE_08004; + + case SqlState::S08S01_LINK_FAILURE: + return STATE_08S01; + case SqlState::SHY000_GENERAL_ERROR: return STATE_HY000; @@ -269,6 +353,9 @@ namespace ignite case SqlState::SHY092_OPTION_TYPE_OUT_OF_RANGE: return STATE_HY092; + case SqlState::SHY097_COLUMN_TYPE_OUT_OF_RANGE: + return STATE_HY097; + case SqlState::SHY105_INVALID_PARAMETER_TYPE: return STATE_HY105; @@ -278,7 +365,7 @@ namespace ignite case SqlState::SHYC00_OPTIONAL_FEATURE_NOT_IMPLEMENTED: return STATE_HYC00; - case SqlState::SHYT01_CONNECTIOIN_TIMEOUT: + case SqlState::SHYT01_CONNECTION_TIMEOUT: return STATE_HYT01; case SqlState::SIM001_FUNCTION_NOT_SUPPORTED: http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/message.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/message.cpp b/modules/platforms/cpp/odbc/src/message.cpp index 9930290..3601591 100644 --- a/modules/platforms/cpp/odbc/src/message.cpp +++ b/modules/platforms/cpp/odbc/src/message.cpp @@ -206,7 +206,9 @@ namespace ignite writer.WriteObject<std::string>(sqlQuery); } - Response::Response(): status(ResponseStatus::FAILED), error() + Response::Response() : + status(ResponseStatus::UNKNOWN_ERROR), + error() { // No-op. } @@ -216,17 +218,20 @@ namespace ignite // No-op. } - void Response::Read(impl::binary::BinaryReaderImpl& reader) + void Response::Read(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion& ver) { - status = reader.ReadInt8(); + if (ver < ProtocolVersion::VERSION_2_1_5) + status = reader.ReadInt8(); + else + status = reader.ReadInt32(); if (status == ResponseStatus::SUCCESS) - ReadOnSuccess(reader); + ReadOnSuccess(reader, ver); else utility::ReadString(reader, error);; } - void Response::ReadOnSuccess(impl::binary::BinaryReaderImpl&) + void Response::ReadOnSuccess(impl::binary::BinaryReaderImpl&, const ProtocolVersion&) { // No-op. } @@ -244,7 +249,7 @@ namespace ignite // No-op. } - void HandshakeResponse::Read(impl::binary::BinaryReaderImpl& reader) + void HandshakeResponse::Read(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { accepted = reader.ReadBool(); @@ -270,7 +275,7 @@ namespace ignite // No-op. } - void QueryCloseResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryCloseResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { queryId = reader.ReadInt64(); } @@ -288,7 +293,7 @@ namespace ignite // No-op. } - void QueryExecuteResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryExecuteResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { queryId = reader.ReadInt64(); @@ -300,7 +305,8 @@ namespace ignite QueryExecuteBatchResponse::QueryExecuteBatchResponse(): affectedRows(0), errorSetIdx(-1), - errorMessage() + errorMessage(), + errorCode(1) { // No-op. } @@ -310,7 +316,7 @@ namespace ignite // No-op. } - void QueryExecuteBatchResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryExecuteBatchResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion& ver) { bool success = reader.ReadBool(); affectedRows = reader.ReadInt64(); @@ -319,6 +325,9 @@ namespace ignite { errorSetIdx = reader.ReadInt64(); errorMessage = reader.ReadObject<std::string>(); + + if (ver >= ProtocolVersion::VERSION_2_1_5) + errorCode = reader.ReadInt32(); } } @@ -332,7 +341,7 @@ namespace ignite // No-op. } - void QueryFetchResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryFetchResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { queryId = reader.ReadInt64(); @@ -349,7 +358,7 @@ namespace ignite // No-op. } - void QueryGetColumnsMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryGetColumnsMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { meta::ReadColumnMetaVector(reader, meta); } @@ -364,7 +373,7 @@ namespace ignite // No-op. } - void QueryGetTablesMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryGetTablesMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { meta::ReadTableMetaVector(reader, meta); } @@ -379,7 +388,7 @@ namespace ignite // No-op. } - void QueryGetParamsMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader) + void QueryGetParamsMetaResponse::ReadOnSuccess(impl::binary::BinaryReaderImpl& reader, const ProtocolVersion&) { utility::ReadByteArray(reader, typeIds); } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/query/batch_query.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/query/batch_query.cpp b/modules/platforms/cpp/odbc/src/query/batch_query.cpp index 46447c0..fc8fda4 100644 --- a/modules/platforms/cpp/odbc/src/query/batch_query.cpp +++ b/modules/platforms/cpp/odbc/src/query/batch_query.cpp @@ -18,6 +18,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/log.h" +#include "ignite/odbc/odbc_error.h" #include "ignite/odbc/query/batch_query.h" namespace ignite @@ -160,9 +161,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -171,7 +178,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } @@ -186,7 +193,7 @@ namespace ignite setsProcessed += rsp.GetErrorSetIdx(); LOG_MSG("setsProcessed: " << setsProcessed); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetErrorMessage(), + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetErrorCode()), rsp.GetErrorMessage(), static_cast<int32_t>(setsProcessed), 0); return SqlResult::AI_SUCCESS_WITH_INFO; http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp index b9c08f5..0910612 100644 --- a/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp +++ b/modules/platforms/cpp/odbc/src/query/column_metadata_query.cpp @@ -21,6 +21,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/log.h" +#include "ignite/odbc/odbc_error.h" #include "ignite/odbc/query/column_metadata_query.h" namespace @@ -297,9 +298,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -307,7 +314,7 @@ namespace ignite if (rsp.GetStatus() != ResponseStatus::SUCCESS) { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/query/data_query.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/query/data_query.cpp b/modules/platforms/cpp/odbc/src/query/data_query.cpp index 245e0bd..80fcc69 100644 --- a/modules/platforms/cpp/odbc/src/query/data_query.cpp +++ b/modules/platforms/cpp/odbc/src/query/data_query.cpp @@ -18,6 +18,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/log.h" +#include "ignite/odbc/odbc_error.h" #include "ignite/odbc/query/data_query.h" #include "ignite/odbc/query/batch_query.h" @@ -193,9 +194,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -204,7 +211,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } @@ -241,9 +248,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -254,7 +267,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } @@ -273,9 +286,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -284,7 +303,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp b/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp index e66b281..93f1f79 100644 --- a/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp +++ b/modules/platforms/cpp/odbc/src/query/table_metadata_query.cpp @@ -21,6 +21,7 @@ #include "ignite/odbc/connection.h" #include "ignite/odbc/message.h" #include "ignite/odbc/log.h" +#include "ignite/odbc/odbc_error.h" #include "ignite/odbc/query/table_metadata_query.h" namespace @@ -223,9 +224,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + diag.AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - diag.AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -234,7 +241,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - diag.AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + diag.AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; } http://git-wip-us.apache.org/repos/asf/ignite/blob/fc34091c/modules/platforms/cpp/odbc/src/statement.cpp ---------------------------------------------------------------------- diff --git a/modules/platforms/cpp/odbc/src/statement.cpp b/modules/platforms/cpp/odbc/src/statement.cpp index a74a413..36c1a0b 100644 --- a/modules/platforms/cpp/odbc/src/statement.cpp +++ b/modules/platforms/cpp/odbc/src/statement.cpp @@ -29,6 +29,7 @@ #include "ignite/odbc/message.h" #include "ignite/odbc/statement.h" #include "ignite/odbc/log.h" +#include "ignite/odbc/odbc_error.h" namespace ignite { @@ -1104,9 +1105,15 @@ namespace ignite { connection.SyncMessage(req, rsp); } + catch (const OdbcError& err) + { + AddStatusRecord(err); + + return SqlResult::AI_ERROR; + } catch (const IgniteError& err) { - AddStatusRecord(SqlState::SHYT01_CONNECTIOIN_TIMEOUT, err.GetText()); + AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, err.GetText()); return SqlResult::AI_ERROR; } @@ -1115,7 +1122,7 @@ namespace ignite { LOG_MSG("Error: " << rsp.GetError()); - AddStatusRecord(SqlState::SHY000_GENERAL_ERROR, rsp.GetError()); + AddStatusRecord(ResponseStatusToSqlState(rsp.GetStatus()), rsp.GetError()); return SqlResult::AI_ERROR; }
