You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by vo...@apache.org on 2018/10/15 07:47:34 UTC
ignite git commit: IGNITE-9620: MVCC: throw specific SQLSTATE code
(40001) in case of write conflict. This closes #4952.
Repository: ignite
Updated Branches:
refs/heads/master 11716dedc -> 3ebc740f1
IGNITE-9620: MVCC: throw specific SQLSTATE code (40001) in case of write conflict. This closes #4952.
Project: http://git-wip-us.apache.org/repos/asf/ignite/repo
Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/3ebc740f
Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/3ebc740f
Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/3ebc740f
Branch: refs/heads/master
Commit: 3ebc740f11464df42f2b8e5e1d7adcda458f7b05
Parents: 11716de
Author: devozerov <vo...@gridgain.com>
Authored: Mon Oct 15 10:47:26 2018 +0300
Committer: devozerov <vo...@gridgain.com>
Committed: Mon Oct 15 10:47:26 2018 +0300
----------------------------------------------------------------------
.../jdbc/JdbcVersionMismatchSelfTest.java | 171 +++++++++++++
.../suite/IgniteJdbcDriverMvccTestSuite.java | 4 +-
...ThinTransactionsAbstractComplexSelfTest.java | 4 +-
.../internal/jdbc/thin/JdbcThinConnection.java | 2 +-
.../processors/cache/GridCacheMapEntry.java | 21 +-
.../cache/query/IgniteQueryErrorCode.java | 6 +
.../internal/processors/odbc/SqlStateCode.java | 3 +
.../processors/query/h2/IgniteH2Indexing.java | 6 +-
.../cache/mvcc/CacheMvccSizeTest.java | 4 +-
.../cache/mvcc/CacheMvccSqlLockTimeoutTest.java | 2 +-
.../mvcc/CacheMvccSqlTxQueriesAbstractTest.java | 2 +-
...MvccSqlTxQueriesWithReducerAbstractTest.java | 2 +-
.../cpp/odbc-test/include/odbc_test_suite.h | 11 +-
.../cpp/odbc-test/include/test_utils.h | 59 +++++
.../cpp/odbc-test/src/odbc_test_suite.cpp | 28 +++
.../platforms/cpp/odbc-test/src/test_utils.cpp | 15 ++
.../cpp/odbc-test/src/transaction_test.cpp | 244 +++++++++++++------
.../cpp/odbc/include/ignite/odbc/common_types.h | 14 +-
modules/platforms/cpp/odbc/src/common_types.cpp | 8 +-
.../odbc/src/diagnostic/diagnostic_record.cpp | 12 +
.../mvcc/MvccUpdateContentionBenchmark.java | 4 +-
21 files changed, 532 insertions(+), 90 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcVersionMismatchSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcVersionMismatchSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcVersionMismatchSelfTest.java
new file mode 100644
index 0000000..19e18a2
--- /dev/null
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/JdbcVersionMismatchSelfTest.java
@@ -0,0 +1,171 @@
+/*
+ * 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 org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode;
+import org.apache.ignite.internal.processors.odbc.SqlStateCode;
+import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * JDBC version mismatch test.
+ */
+public class JdbcVersionMismatchSelfTest extends GridCommonAbstractTest {
+ /** {@inheritDoc} */
+ @Override protected void beforeTest() throws Exception {
+ startGrid();
+
+ try (Connection conn = connect()) {
+ executeUpdate(conn,
+ "CREATE TABLE test (a INT PRIMARY KEY, b INT, c VARCHAR) WITH \"atomicity=TRANSACTIONAL_SNAPSHOT, cache_name=TEST\"");
+
+ executeUpdate(conn, "INSERT INTO test VALUES (1, 1, 'test_1')");
+ }
+ }
+
+ /** {@inheritDoc} */
+ @Override protected void afterTest() throws Exception {
+ stopAllGrids();
+ }
+
+ /**
+ * @throws Exception If failed.
+ */
+ public void testVersionMismatchJdbc() throws Exception {
+ try (Connection conn1 = connect(); Connection conn2 = connect()) {
+ conn1.setAutoCommit(false);
+ conn2.setAutoCommit(false);
+
+ // Start first transaction and observe some values.
+ assertEquals(1, executeQuery(conn1, "SELECT * FROM test").size());
+
+ // Change values while first transaction is still in progress.
+ executeUpdate(conn2, "INSERT INTO test VALUES (2, 2, 'test_2')");
+ executeUpdate(conn2, "COMMIT");
+ assertEquals(2, executeQuery(conn2, "SELECT * FROM test").size());
+
+ // Force version mismatch.
+ try {
+ executeUpdate(conn1, "INSERT INTO test VALUES (2, 2, 'test_2')");
+
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals(SqlStateCode.SERIALIZATION_FAILURE, e.getSQLState());
+ assertEquals(IgniteQueryErrorCode.TRANSACTION_SERIALIZATION_ERROR, e.getErrorCode());
+
+ assertNotNull(e.getMessage());
+ assertTrue(e.getMessage().contains("Cannot serialize transaction due to write conflict"));
+ }
+
+ // Subsequent call should cause exception due to TX being rolled back.
+ try {
+ executeQuery(conn1, "SELECT * FROM test").size();
+
+ fail();
+ }
+ catch (SQLException e) {
+ assertEquals(SqlStateCode.TRANSACTION_STATE_EXCEPTION, e.getSQLState());
+ assertEquals(IgniteQueryErrorCode.TRANSACTION_COMPLETED, e.getErrorCode());
+
+ assertNotNull(e.getMessage());
+ assertTrue(e.getMessage().contains("Transaction is already completed"));
+ }
+
+ // Commit should fail.
+ try {
+ conn1.commit();
+
+ fail();
+ }
+ catch (SQLException e) {
+ // Cannot pass proper error codes for now
+ assertEquals(SqlStateCode.INTERNAL_ERROR, e.getSQLState());
+ assertEquals(IgniteQueryErrorCode.UNKNOWN, e.getErrorCode());
+
+ assertNotNull(e.getMessage());
+ assertTrue(e.getMessage().contains("Failed to finish transaction because it has been rolled back"));
+ }
+
+ // Rollback should work.
+ conn1.rollback();
+
+ // Subsequent calls should work fine.
+ assertEquals(2, executeQuery(conn2, "SELECT * FROM test").size());
+ }
+ }
+
+ /**
+ * Establish JDBC connection.
+ *
+ * @return Connection.
+ * @throws Exception If failed.
+ */
+ private Connection connect() throws Exception {
+ return DriverManager.getConnection("jdbc:ignite:thin://127.0.0.1:10800");
+ }
+
+ /**
+ * Execute update statement.
+ *
+ * @param conn Connection.
+ * @param sql SQL.
+ * @throws Exception If failed.
+ */
+ private static void executeUpdate(Connection conn, String sql) throws Exception {
+ try (Statement stmt = conn.createStatement()) {
+ stmt.executeUpdate(sql);
+ }
+ }
+
+ /**
+ * Execute query.
+ *
+ * @param conn Connection.
+ * @param sql SQL.
+ * @return Result.
+ * @throws Exception If failed.
+ */
+ private static List<List<Object>> executeQuery(Connection conn, String sql) throws Exception {
+ List<List<Object>> rows = new ArrayList<>();
+
+ try (Statement stmt = conn.createStatement()) {
+ try (ResultSet rs = stmt.executeQuery(sql)) {
+ int colCnt = rs.getMetaData().getColumnCount();
+
+ while (rs.next()) {
+ List<Object> row = new ArrayList<>(colCnt);
+
+ for (int i = 0; i < colCnt; i++)
+ row.add(rs.getObject(i + 1));
+
+ rows.add(row);
+ }
+ }
+ }
+
+ return rows;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverMvccTestSuite.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverMvccTestSuite.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverMvccTestSuite.java
index 6d8933d..606c32d 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverMvccTestSuite.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/suite/IgniteJdbcDriverMvccTestSuite.java
@@ -18,12 +18,13 @@
package org.apache.ignite.jdbc.suite;
import junit.framework.TestSuite;
+import org.apache.ignite.jdbc.JdbcVersionMismatchSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinConnectionMvccEnabledSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinTransactionsClientAutoCommitComplexSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinTransactionsClientNoAutoCommitComplexSelfTest;
-import org.apache.ignite.jdbc.thin.JdbcThinTransactionsWithMvccEnabledSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinTransactionsServerAutoCommitComplexSelfTest;
import org.apache.ignite.jdbc.thin.JdbcThinTransactionsServerNoAutoCommitComplexSelfTest;
+import org.apache.ignite.jdbc.thin.JdbcThinTransactionsWithMvccEnabledSelfTest;
public class IgniteJdbcDriverMvccTestSuite extends TestSuite {
/**
@@ -34,6 +35,7 @@ public class IgniteJdbcDriverMvccTestSuite extends TestSuite {
TestSuite suite = new TestSuite("Ignite JDBC Driver Test Suite");
suite.addTest(new TestSuite(JdbcThinConnectionMvccEnabledSelfTest.class));
+ suite.addTest(new TestSuite(JdbcVersionMismatchSelfTest.class));
// Transactions
suite.addTest(new TestSuite(JdbcThinTransactionsWithMvccEnabledSelfTest.class));
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
----------------------------------------------------------------------
diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
index 68ed36b..a175568 100644
--- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
+++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsAbstractComplexSelfTest.java
@@ -755,11 +755,11 @@ public abstract class JdbcThinTransactionsAbstractComplexSelfTest extends JdbcTh
return null;
}
- }, IgniteCheckedException.class, "Mvcc version mismatch.");
+ }, IgniteCheckedException.class, "Cannot serialize transaction due to write conflict");
assertTrue(X.hasCause(ex, SQLException.class));
- assertTrue(X.getCause(ex).getMessage().contains("Mvcc version mismatch."));
+ assertTrue(X.getCause(ex).getMessage().contains("Cannot serialize transaction due to write conflict"));
}
else
readFut.get();
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinConnection.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 323a410..d92948c 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
@@ -747,7 +747,7 @@ public class JdbcThinConnection implements Connection {
JdbcResponse res = cliIo.sendRequest(req);
if (res.status() != ClientListenerResponse.STATUS_SUCCESS)
- throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status()));
+ throw new SQLException(res.error(), IgniteQueryErrorCode.codeToSqlState(res.status()), res.status());
return (R)res.response();
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
----------------------------------------------------------------------
diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
index 1a04bd2..d417bd4 100644
--- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
+++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/GridCacheMapEntry.java
@@ -118,6 +118,7 @@ import static org.apache.ignite.internal.processors.cache.GridCacheUpdateAtomicR
import static org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter.RowData.NO_KEY;
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.TRANSACTION_SERIALIZATION_ERROR;
import static org.apache.ignite.internal.processors.dr.GridDrType.DR_BACKUP;
import static org.apache.ignite.internal.processors.dr.GridDrType.DR_NONE;
import static org.apache.ignite.internal.processors.dr.GridDrType.DR_PRIMARY;
@@ -1111,7 +1112,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res.resultType() != ResultType.PREV_NOT_NULL || op != CREATE || tx.local();
if (res.resultType() == ResultType.VERSION_MISMATCH)
- throw new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE);
+ throw serializationError();
else if (res.resultType() == ResultType.FILTERED) {
GridCacheUpdateTxResult updRes = new GridCacheUpdateTxResult(invoke);
@@ -1261,7 +1262,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH)
- throw new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE);
+ throw serializationError();
else if (res.resultType() == ResultType.PREV_NULL || res.resultType() == ResultType.FILTERED)
return new GridCacheUpdateTxResult(false);
else if (res.resultType() == ResultType.LOCKED) {
@@ -1358,7 +1359,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH)
- throw new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE);
+ throw serializationError();
else if (res.resultType() == ResultType.LOCKED) {
unlockEntry();
@@ -5069,7 +5070,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH) {
- resFut.onDone(new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE));
+ resFut.onDone(serializationError());
return;
}
@@ -5212,7 +5213,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH) {
- resFut.onDone(new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE));
+ resFut.onDone(serializationError());
return;
}
@@ -5382,7 +5383,7 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
assert res != null;
if (res.resultType() == ResultType.VERSION_MISMATCH) {
- resFut.onDone(new IgniteSQLException("Mvcc version mismatch.", CONCURRENT_UPDATE));
+ resFut.onDone(serializationError());
return;
}
@@ -6654,4 +6655,12 @@ public abstract class GridCacheMapEntry extends GridMetadataAwareAdapter impleme
return new GridCacheUpdateTxResult(true, logPtr);
}
+
+ /**
+ * @return Common serialization error.
+ */
+ @SuppressWarnings("UnnecessaryReturnStatement")
+ private static IgniteSQLException serializationError() {
+ return new IgniteSQLException("Cannot serialize transaction due to write conflict (transaction is marked for rollback)", TRANSACTION_SERIALIZATION_ERROR);
+ }
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/query/IgniteQueryErrorCode.java
----------------------------------------------------------------------
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 5dab5fd..f1a2355 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
@@ -120,6 +120,9 @@ public final class IgniteQueryErrorCode {
/** Transaction is already completed. */
public final static int TRANSACTION_COMPLETED = 5004;
+ /** Transaction serialization error. */
+ public final static int TRANSACTION_SERIALIZATION_ERROR = 5005;
+
/** */
private IgniteQueryErrorCode() {
// No-op.
@@ -179,6 +182,9 @@ public final class IgniteQueryErrorCode {
case TRANSACTION_COMPLETED:
return SqlStateCode.TRANSACTION_STATE_EXCEPTION;
+ case TRANSACTION_SERIALIZATION_ERROR:
+ return SqlStateCode.SERIALIZATION_FAILURE;
+
default:
return SqlStateCode.INTERNAL_ERROR;
}
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/core/src/main/java/org/apache/ignite/internal/processors/odbc/SqlStateCode.java
----------------------------------------------------------------------
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 68ac200..0b9423f 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
@@ -64,6 +64,9 @@ public final class SqlStateCode {
/** Transaction state exception. */
public final static String TRANSACTION_STATE_EXCEPTION = "25000";
+ /** Transaction state exception. */
+ public final static String SERIALIZATION_FAILURE = "40001";
+
/** Parsing exception. */
public final static String PARSING_EXCEPTION = "42000";
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
index c4d5eea..e3fef49 100644
--- a/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
+++ b/modules/indexing/src/main/java/org/apache/ignite/internal/processors/query/h2/IgniteH2Indexing.java
@@ -2021,7 +2021,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
return Collections.singletonList(H2Utils.zeroCursor());
}
catch (IgniteCheckedException e) {
- throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + qry.getSql() + ']', e);
+ throw new IgniteSQLException("Failed to execute DDL statement [stmt=" + qry.getSql() +
+ ", err=" + e.getMessage() + ']', e);
}
}
@@ -2107,7 +2108,8 @@ public class IgniteH2Indexing implements GridQueryIndexing {
@SuppressWarnings("ThrowFromFinallyBlock")
private void doCommit(@NotNull GridNearTxLocal tx) throws IgniteCheckedException {
try {
- if (!tx.isRollbackOnly())
+ // TODO: Why checking for rollback only?
+ //if (!tx.isRollbackOnly())
tx.commit();
}
finally {
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSizeTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSizeTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSizeTest.java
index fe1304a..36a2322 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSizeTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSizeTest.java
@@ -127,7 +127,7 @@ public class CacheMvccSizeTest extends CacheMvccAbstractTest {
}
}
},
- true, 0);
+ false, 0);
checkSizeModificationByOperation("merge into person(id, name) values(1, 'a')", true, 1);
@@ -298,7 +298,7 @@ public class CacheMvccSizeTest extends CacheMvccAbstractTest {
}
catch (Exception e) {
if (e.getCause().getCause() instanceof IgniteSQLException)
- assertTrue(e.getMessage().toLowerCase().contains("version mismatch"));
+ assertTrue(e.getMessage().contains("Failed to finish transaction because it has been rolled back"));
else {
e.printStackTrace();
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlLockTimeoutTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlLockTimeoutTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlLockTimeoutTest.java
index eae79a5..bdd9a76 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlLockTimeoutTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlLockTimeoutTest.java
@@ -343,7 +343,7 @@ public class CacheMvccSqlLockTimeoutTest extends CacheMvccAbstractTest {
}
catch (Exception e) {
assertTrue(msgContains(e, "Failed to acquire lock within provided timeout for transaction")
- || msgContains(e, "Mvcc version mismatch"));
+ || msgContains(e, "Cannot serialize transaction due to write conflict"));
}
finally {
ignite.context().cache().context().tm().resetContext();
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
index 7076362..4abcaa1 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesAbstractTest.java
@@ -1287,7 +1287,7 @@ public abstract class CacheMvccSqlTxQueriesAbstractTest extends CacheMvccAbstrac
IgniteSQLException ex0 = X.cause(ex.get(), IgniteSQLException.class);
assertNotNull("Exception has not been thrown.", ex0);
- assertEquals("Mvcc version mismatch.", ex0.getMessage());
+ assertTrue(ex0.getMessage().startsWith("Cannot serialize transaction due to write conflict"));
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
----------------------------------------------------------------------
diff --git a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
index a7cf292..7826e5f 100644
--- a/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
+++ b/modules/indexing/src/test/java/org/apache/ignite/internal/processors/cache/mvcc/CacheMvccSqlTxQueriesWithReducerAbstractTest.java
@@ -680,7 +680,7 @@ public abstract class CacheMvccSqlTxQueriesWithReducerAbstractTest extends Cache
IgniteSQLException ex0 = X.cause(ex.get(), IgniteSQLException.class);
assertNotNull("Exception has not been thrown.", ex0);
- assertEquals("Mvcc version mismatch.", ex0.getMessage());
+ assertTrue(ex0.getMessage().startsWith("Cannot serialize transaction due to write conflict"));
}
/**
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
index 7a33c6a..2381130 100644
--- a/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
+++ b/modules/platforms/cpp/odbc-test/include/odbc_test_suite.h
@@ -44,7 +44,16 @@ namespace ignite
void Prepare();
/**
- * Establish connection to node.
+ * Establish connection to node using provided handles.
+ *
+ * @param conn Connection.
+ * @param statement Statement to allocate.
+ * @param connectStr Connection string.
+ */
+ void Connect(SQLHDBC& conn, SQLHSTMT& statement, const std::string& connectStr);
+
+ /**
+ * Establish connection to node using default handles.
*
* @param connectStr Connection string.
*/
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/platforms/cpp/odbc-test/include/test_utils.h
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/include/test_utils.h b/modules/platforms/cpp/odbc-test/include/test_utils.h
index a1de23e..58a4347 100644
--- a/modules/platforms/cpp/odbc-test/include/test_utils.h
+++ b/modules/platforms/cpp/odbc-test/include/test_utils.h
@@ -29,6 +29,12 @@
#include "ignite/ignition.h"
+#define ODBC_THROW_ON_ERROR(ret, type, handle) \
+ if (!SQL_SUCCEEDED(ret)) \
+ { \
+ throw ignite_test::GetOdbcError(type, handle); \
+ }
+
#define ODBC_FAIL_ON_ERROR(ret, type, handle) \
if (!SQL_SUCCEEDED(ret)) \
{ \
@@ -43,6 +49,50 @@
BOOST_FAIL(ignite_test::GetOdbcErrorMessage(type, handle) + ", msg = " + msg); \
}
+/**
+ * Client ODBC erorr.
+ */
+class OdbcClientError : public std::exception
+{
+public:
+ /**
+ * Constructor
+ *
+ * @param sqlstate SQL state.
+ * @param message Error message.
+ */
+ OdbcClientError(const std::string& sqlstate, const std::string& message) :
+ sqlstate(sqlstate),
+ message(message)
+ {
+ // No-op.
+ }
+
+ /**
+ * Destructor.
+ */
+ virtual ~OdbcClientError() IGNITE_NO_THROW
+ {
+ // No-op.
+ }
+
+ /**
+ * Implementation of the standard std::exception::what() method.
+ * Synonym for GetText() method.
+ *
+ * @return Error message string.
+ */
+ virtual const char* what() const IGNITE_NO_THROW
+ {
+ return message.c_str();
+ }
+
+ /** SQL state. */
+ std::string sqlstate;
+
+ /** Error message. */
+ std::string message;
+};
namespace ignite_test
{
@@ -50,6 +100,15 @@ namespace ignite_test
enum { ODBC_BUFFER_SIZE = 1024 };
/**
+ * Extract error.
+ *
+ * @param handleType Type of the handle.
+ * @param handle Handle.
+ * @return Error.
+ */
+ OdbcClientError GetOdbcError(SQLSMALLINT handleType, SQLHANDLE handle);
+
+ /**
* Extract error state.
*
* @param handleType Type of the handle.
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
index 4f5be91..b79d13a 100644
--- a/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
+++ b/modules/platforms/cpp/odbc-test/src/odbc_test_suite.cpp
@@ -56,6 +56,34 @@ namespace ignite
BOOST_REQUIRE(dbc != NULL);
}
+ void OdbcTestSuite::Connect(SQLHDBC& conn, SQLHSTMT& statement, const std::string& connectStr)
+ {
+ // Allocate a connection handle
+ SQLAllocHandle(SQL_HANDLE_DBC, env, &conn);
+
+ BOOST_REQUIRE(conn != NULL);
+
+ // Connect string
+ std::vector<SQLCHAR> connectStr0(connectStr.begin(), connectStr.end());
+
+ SQLCHAR outstr[ODBC_BUFFER_SIZE];
+ SQLSMALLINT outstrlen;
+
+ // Connecting to ODBC server.
+ SQLRETURN ret = SQLDriverConnect(conn, NULL, &connectStr0[0], static_cast<SQLSMALLINT>(connectStr0.size()),
+ outstr, sizeof(outstr), &outstrlen, SQL_DRIVER_COMPLETE);
+
+ if (!SQL_SUCCEEDED(ret))
+ {
+ BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_DBC, conn));
+ }
+
+ // Allocate a statement handle
+ SQLAllocHandle(SQL_HANDLE_STMT, conn, &statement);
+
+ BOOST_REQUIRE(statement != NULL);
+ }
+
void OdbcTestSuite::Connect(const std::string& connectStr)
{
Prepare();
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/platforms/cpp/odbc-test/src/test_utils.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/test_utils.cpp b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
index fc8cbd3..68bd787 100644
--- a/modules/platforms/cpp/odbc-test/src/test_utils.cpp
+++ b/modules/platforms/cpp/odbc-test/src/test_utils.cpp
@@ -23,6 +23,21 @@
namespace ignite_test
{
+ OdbcClientError GetOdbcError(SQLSMALLINT handleType, SQLHANDLE handle)
+ {
+ SQLCHAR sqlstate[7] = {};
+ SQLINTEGER nativeCode;
+
+ SQLCHAR message[ODBC_BUFFER_SIZE];
+ SQLSMALLINT reallen = 0;
+
+ SQLGetDiagRec(handleType, handle, 1, sqlstate, &nativeCode, message, ODBC_BUFFER_SIZE, &reallen);
+
+ return OdbcClientError(
+ std::string(reinterpret_cast<char*>(sqlstate)),
+ std::string(reinterpret_cast<char*>(message), reallen));
+ }
+
std::string GetOdbcErrorState(SQLSMALLINT handleType, SQLHANDLE handle)
{
SQLCHAR sqlstate[7] = {};
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/platforms/cpp/odbc-test/src/transaction_test.cpp
----------------------------------------------------------------------
diff --git a/modules/platforms/cpp/odbc-test/src/transaction_test.cpp b/modules/platforms/cpp/odbc-test/src/transaction_test.cpp
index 73e54b8..ed1b054 100644
--- a/modules/platforms/cpp/odbc-test/src/transaction_test.cpp
+++ b/modules/platforms/cpp/odbc-test/src/transaction_test.cpp
@@ -75,51 +75,56 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void InsertTestValue(int64_t key, const std::string& value)
{
- SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
+ InsertTestValue(stmt, key, value);
+ }
- SQLRETURN ret;
+ /**
+ * Insert test string value in cache and make all the neccessary checks.
+ *
+ * @param stmt Statement.
+ * @param key Key.
+ * @param value Value.
+ */
+ static void InsertTestValue(SQLHSTMT stmt, int64_t key, const std::string& value)
+ {
+ SQLCHAR insertReq[] = "INSERT INTO TestType(_key, strField) VALUES(?, ?)";
- ret = SQLPrepare(stmt, insertReq, SQL_NTS);
+ SQLRETURN ret = SQLPrepare(stmt, insertReq, SQL_NTS);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
char strField[1024] = { 0 };
SQLLEN strFieldLen = 0;
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField),
sizeof(strField), &strField, sizeof(strField), &strFieldLen);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
strncpy(strField, value.c_str(), sizeof(strField));
strFieldLen = SQL_NTS;
ret = SQLExecute(stmt);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
SQLLEN affected = 0;
ret = SQLRowCount(stmt, &affected);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(affected, 1);
ret = SQLMoreResults(stmt);
if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
- ResetStatement();
+ ResetStatement(stmt);
}
/**
@@ -130,14 +135,23 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void UpdateTestValue(int64_t key, const std::string& value)
{
- SQLCHAR insertReq[] = "UPDATE TestType SET strField=? WHERE _key=?";
+ UpdateTestValue(stmt, key, value);
+ }
- SQLRETURN ret;
+ /**
+ * Update test string value in cache and make all the neccessary checks.
+ *
+ * @param stmt Statement.
+ * @param key Key.
+ * @param value Value.
+ */
+ static void UpdateTestValue(SQLHSTMT stmt, int64_t key, const std::string& value)
+ {
+ SQLCHAR insertReq[] = "UPDATE TestType SET strField=? WHERE _key=?";
- ret = SQLPrepare(stmt, insertReq, SQL_NTS);
+ SQLRETURN ret = SQLPrepare(stmt, insertReq, SQL_NTS);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
char strField[1024] = { 0 };
SQLLEN strFieldLen = 0;
@@ -145,36 +159,32 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_CHAR, SQL_VARCHAR, sizeof(strField),
sizeof(strField), &strField, sizeof(strField), &strFieldLen);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindParameter(stmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
strncpy(strField, value.c_str(), sizeof(strField));
strFieldLen = SQL_NTS;
ret = SQLExecute(stmt);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
SQLLEN affected = 0;
ret = SQLRowCount(stmt, &affected);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(affected, 1);
ret = SQLMoreResults(stmt);
if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
- ResetStatement();
+ ResetStatement(stmt);
}
/**
@@ -184,41 +194,45 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void DeleteTestValue(int64_t key)
{
- SQLCHAR insertReq[] = "DELETE FROM TestType WHERE _key=?";
+ DeleteTestValue(stmt, key);
+ }
- SQLRETURN ret;
+ /**
+ * Delete test string value.
+ *
+ * @param stmt Statement.
+ * @param key Key.
+ */
+ static void DeleteTestValue(SQLHSTMT stmt, int64_t key)
+ {
+ SQLCHAR insertReq[] = "DELETE FROM TestType WHERE _key=?";
- ret = SQLPrepare(stmt, insertReq, SQL_NTS);
+ SQLRETURN ret = SQLPrepare(stmt, insertReq, SQL_NTS);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLExecute(stmt);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
SQLLEN affected = 0;
ret = SQLRowCount(stmt, &affected);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(affected, 1);
ret = SQLMoreResults(stmt);
if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
- ResetStatement();
+ ResetStatement(stmt);
}
-
/**
* Selects and checks the value.
*
@@ -227,6 +241,18 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void CheckTestValue(int64_t key, const std::string& expect)
{
+ CheckTestValue(stmt, key, expect);
+ }
+
+ /**
+ * Selects and checks the value.
+ *
+ * @param stmt Statement.
+ * @param key Key.
+ * @param expect Expected value.
+ */
+ static void CheckTestValue(SQLHSTMT stmt, int64_t key, const std::string& expect)
+ {
// Just selecting everything to make sure everything is OK
SQLCHAR selectReq[] = "SELECT strField FROM TestType WHERE _key = ?";
@@ -235,23 +261,19 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLFetch(stmt);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
BOOST_CHECK_EQUAL(std::string(strField, strFieldLen), expect);
@@ -262,9 +284,9 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
ret = SQLMoreResults(stmt);
if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
- ResetStatement();
+ ResetStatement(stmt);
}
/**
@@ -274,6 +296,17 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void CheckNoTestValue(int64_t key)
{
+ CheckNoTestValue(stmt, key);
+ }
+
+ /**
+ * Selects and checks that value is absent.
+ *
+ * @param stmt Statement.
+ * @param key Key.
+ */
+ static void CheckNoTestValue(SQLHSTMT stmt, int64_t key)
+ {
// Just selecting everything to make sure everything is OK
SQLCHAR selectReq[] = "SELECT strField FROM TestType WHERE _key = ?";
@@ -282,32 +315,31 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
SQLRETURN ret = SQLBindCol(stmt, 1, SQL_C_CHAR, &strField, sizeof(strField), &strFieldLen);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLBindParameter(stmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_BIGINT, 0, 0, &key, 0, 0);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLExecDirect(stmt, selectReq, sizeof(selectReq));
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLFetch(stmt);
BOOST_CHECK_EQUAL(ret, SQL_NO_DATA);
- if (ret != SQL_NO_DATA && !SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ if (ret != SQL_NO_DATA)
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLMoreResults(stmt);
+ BOOST_CHECK_EQUAL(ret, SQL_NO_DATA);
+
if (ret != SQL_NO_DATA)
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
- ResetStatement();
+ ResetStatement(stmt);
}
/**
@@ -315,15 +347,23 @@ struct TransactionTestSuiteFixture : public odbc::OdbcTestSuite
*/
void ResetStatement()
{
+ ResetStatement(stmt);
+ }
+
+ /**
+ * Reset statement state.
+ *
+ * @param stmt Statement.
+ */
+ static void ResetStatement(SQLHSTMT stmt)
+ {
SQLRETURN ret = SQLFreeStmt(stmt, SQL_RESET_PARAMS);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
ret = SQLFreeStmt(stmt, SQL_UNBIND);
- if (!SQL_SUCCEEDED(ret))
- BOOST_FAIL(GetOdbcErrorMessage(SQL_HANDLE_STMT, stmt));
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_STMT, stmt);
}
/** Node started during the test. */
@@ -738,4 +778,72 @@ BOOST_AUTO_TEST_CASE(TransactionEnvironmentTxModeCommit)
CheckTestValue(42, "Some");
}
+BOOST_AUTO_TEST_CASE(TransactionVersionMismatchError)
+{
+ Connect("DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+ InsertTestValue(1, "test_1");
+
+ SQLRETURN ret = SQLSetConnectAttr(dbc, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0);
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+ CheckTestValue(1, "test_1");
+
+ SQLHDBC dbc2;
+ SQLHSTMT stmt2;
+
+ Connect(dbc2, stmt2, "DRIVER={Apache Ignite};address=127.0.0.1:11110;schema=cache");
+
+ ret = SQLSetConnectAttr(dbc2, SQL_ATTR_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF, 0);
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc2);
+
+ InsertTestValue(stmt2, 2, "test_2");
+
+ ret = SQLEndTran(SQL_HANDLE_DBC, dbc2, SQL_COMMIT);
+
+ ODBC_FAIL_ON_ERROR(ret, SQL_HANDLE_DBC, dbc2);
+
+ CheckTestValue(stmt2, 1, "test_1");
+ CheckTestValue(stmt2, 2, "test_2");
+
+ try
+ {
+ InsertTestValue(2, "test_2");
+
+ BOOST_FAIL("Exception is expected");
+ }
+ catch (OdbcClientError& err)
+ {
+ BOOST_CHECK(err.message.find("Cannot serialize transaction due to write conflict") != err.message.npos);
+ BOOST_CHECK_EQUAL(err.sqlstate, "40001");
+
+ ResetStatement(stmt);
+ }
+
+ try
+ {
+ CheckTestValue(1, "test_1");
+
+ BOOST_FAIL("Exception is expected");
+ }
+ catch (OdbcClientError& err)
+ {
+ BOOST_CHECK(err.message.find("Transaction is already completed") != err.message.npos);
+ BOOST_CHECK_EQUAL(err.sqlstate, "25000");
+
+ ResetStatement(stmt);
+ }
+
+ ret = SQLEndTran(SQL_HANDLE_DBC, dbc, SQL_ROLLBACK);
+ ODBC_THROW_ON_ERROR(ret, SQL_HANDLE_DBC, dbc);
+
+ SQLFreeHandle(SQL_HANDLE_STMT, stmt2);
+
+ SQLDisconnect(dbc2);
+
+ SQLFreeHandle(SQL_HANDLE_DBC, dbc2);
+}
+
BOOST_AUTO_TEST_SUITE_END()
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/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 29bb022..9241bbc 100644
--- a/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
+++ b/modules/platforms/cpp/odbc/include/ignite/odbc/common_types.h
@@ -95,9 +95,15 @@ namespace ignite
/** Invalid cursor state. */
S24000_INVALID_CURSOR_STATE,
+ /** Invalid transaction state. */
+ S25000_INVALID_TRANSACTION_STATE,
+
/** Invalid schema name. */
S3F000_INVALID_SCHEMA_NAME,
+ /** Serialization failure. */
+ S40001_SERIALIZATION_FAILURE,
+
/** Syntax error or access violation. */
S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION,
@@ -371,7 +377,13 @@ namespace ignite
ENTRY_PROCESSING = 4005,
/** Cache not found. */
- CACHE_NOT_FOUND = 4006
+ CACHE_NOT_FOUND = 4006,
+
+ /** Transaction is already completed. */
+ TRANSACTION_COMPLETED = 5004,
+
+ /** Transaction serialization error. */
+ TRANSACTION_SERIALIZATION_ERROR = 5005
};
};
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/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 10c4f77..72b3cc6 100644
--- a/modules/platforms/cpp/odbc/src/common_types.cpp
+++ b/modules/platforms/cpp/odbc/src/common_types.cpp
@@ -28,7 +28,7 @@ namespace ignite
{
switch (result)
{
- case SqlResult::AI_SUCCESS:
+ case SqlResult::AI_SUCCESS:
return SQL_SUCCESS;
case SqlResult::AI_SUCCESS_WITH_INFO:
@@ -157,6 +157,12 @@ namespace ignite
case ResponseStatus::COLUMN_ALREADY_EXISTS:
return SqlState::S42S21_COLUMN_ALREADY_EXISTS;
+ case ResponseStatus::TRANSACTION_COMPLETED:
+ return SqlState::S25000_INVALID_TRANSACTION_STATE;
+
+ case ResponseStatus::TRANSACTION_SERIALIZATION_ERROR:
+ return SqlState::S40001_SERIALIZATION_FAILURE;
+
case ResponseStatus::CACHE_NOT_FOUND:
case ResponseStatus::NULL_TABLE_DESCRIPTOR:
case ResponseStatus::CONVERSION_FAILED:
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/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 7b82b40..d3a3692 100644
--- a/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
+++ b/modules/platforms/cpp/odbc/src/diagnostic/diagnostic_record.cpp
@@ -79,9 +79,15 @@ namespace
/** SQL state 24000 constant. */
const std::string STATE_24000 = "24000";
+ /** SQL state 25000 constant. */
+ const std::string STATE_25000 = "25000";
+
/** SQL state 3F000 constant. */
const std::string STATE_3F000 = "3F000";
+ /** SQL state 40001 constant. */
+ const std::string STATE_40001 = "40001";
+
/** SQL state 42000 constant. */
const std::string STATE_42000 = "42000";
@@ -305,9 +311,15 @@ namespace ignite
case SqlState::S24000_INVALID_CURSOR_STATE:
return STATE_24000;
+ case SqlState::S25000_INVALID_TRANSACTION_STATE:
+ return STATE_25000;
+
case SqlState::S3F000_INVALID_SCHEMA_NAME:
return STATE_3F000;
+ case SqlState::S40001_SERIALIZATION_FAILURE:
+ return STATE_40001;
+
case SqlState::S42000_SYNTAX_ERROR_OR_ACCESS_VIOLATION:
return STATE_42000;
http://git-wip-us.apache.org/repos/asf/ignite/blob/3ebc740f/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/mvcc/MvccUpdateContentionBenchmark.java
----------------------------------------------------------------------
diff --git a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/mvcc/MvccUpdateContentionBenchmark.java b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/mvcc/MvccUpdateContentionBenchmark.java
index 77c8c50..91128c0 100644
--- a/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/mvcc/MvccUpdateContentionBenchmark.java
+++ b/modules/yardstick/src/main/java/org/apache/ignite/yardstick/jdbc/mvcc/MvccUpdateContentionBenchmark.java
@@ -32,7 +32,7 @@ import static org.yardstickframework.BenchmarkUtils.println;
*/
public class MvccUpdateContentionBenchmark extends AbstractDistributedMvccBenchmark {
/** Expected expception message in mvcc on mode on update fail. */
- private static final String MVCC_EXC_MSG = "Mvcc version mismatch.";
+ private static final String MVCC_EXC_MSG = "Cannot serialize transaction due to write conflict";
/** Expected exception message in mvcc off mode on update fail. */
private static final String NO_MVCC_EXC_MSG_PREFIX =
@@ -53,7 +53,7 @@ public class MvccUpdateContentionBenchmark extends AbstractDistributedMvccBenchm
execute(new SqlFieldsQuery(UPDATE_QRY).setArgs(start, end));
}
catch (IgniteSQLException exc) {
- if ((args.atomicMode() == CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT && !exc.getMessage().equals(MVCC_EXC_MSG)) ||
+ if ((args.atomicMode() == CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT && !exc.getMessage().startsWith(MVCC_EXC_MSG)) ||
(args.atomicMode() != CacheAtomicityMode.TRANSACTIONAL_SNAPSHOT && !exc.getMessage().startsWith(NO_MVCC_EXC_MSG_PREFIX)))
throw new RuntimeException("Exception with unexpected message is thrown.", exc);