Repository: ignite Updated Branches: refs/heads/master 2ad04930d -> ac093b9e3
IGNITE-10004: MVCC: Do not rollback transaction in case of parsing error. This closes #5088. Project: http://git-wip-us.apache.org/repos/asf/ignite/repo Commit: http://git-wip-us.apache.org/repos/asf/ignite/commit/ac093b9e Tree: http://git-wip-us.apache.org/repos/asf/ignite/tree/ac093b9e Diff: http://git-wip-us.apache.org/repos/asf/ignite/diff/ac093b9e Branch: refs/heads/master Commit: ac093b9e343f1f599054406c5421c0cd921392dd Parents: 2ad0493 Author: AMRepo <andrey.mashen...@gmail.com> Authored: Mon Oct 29 16:33:18 2018 +0300 Committer: devozerov <voze...@gridgain.com> Committed: Mon Oct 29 16:33:18 2018 +0300 ---------------------------------------------------------------------- .../jdbc/thin/JdbcThinTransactionsSelfTest.java | 28 ++++++++++++ .../processors/query/h2/IgniteH2Indexing.java | 7 ++- .../mvcc/CacheMvccSqlTxQueriesAbstractTest.java | 48 ++++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ignite/blob/ac093b9e/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsSelfTest.java ---------------------------------------------------------------------- diff --git a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsSelfTest.java b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsSelfTest.java index 1d68712..783a8cd 100644 --- a/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsSelfTest.java +++ b/modules/clients/src/test/java/org/apache/ignite/jdbc/thin/JdbcThinTransactionsSelfTest.java @@ -444,4 +444,32 @@ public class JdbcThinTransactionsSelfTest extends JdbcThinAbstractSelfTest { } } } + + /** + * Test that exception in one of the statements does not kill connection worker altogether. + * @throws SQLException if failed. + */ + @SuppressWarnings("ThrowableResultOfMethodCallIgnored") + public void testParsingErrorHasNoSideEffect() throws SQLException { + try (Connection c = c(false, NestedTxMode.ERROR)) { + try (Statement s = c.createStatement()) { + s.execute("INSERT INTO INTS(k, v) values(1, 1)"); + + GridTestUtils.assertThrows(null, new Callable<Void>() { + @Override public Void call() throws Exception { + s.execute("INSERT INTO INTS(k, v) values(1)"); + + return null; + } + }, SQLException.class, "Failed to parse query"); + + s.execute("INSERT INTO INTS(k, v) values(2, 2)"); + + c.commit(); + } + + assertEquals(1, grid(0).cache("ints").get(1)); + assertEquals(2, grid(0).cache("ints").get(2)); + } + } } http://git-wip-us.apache.org/repos/asf/ignite/blob/ac093b9e/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 3194eed..866ae99 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 @@ -85,6 +85,7 @@ import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.cache.query.QueryTable; import org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx; import org.apache.ignite.internal.processors.cache.transactions.IgniteTxAdapter; +import org.apache.ignite.internal.processors.odbc.SqlStateCode; import org.apache.ignite.internal.processors.query.CacheQueryObjectValueContext; import org.apache.ignite.internal.processors.query.GridQueryCacheObjectsIterator; import org.apache.ignite.internal.processors.query.GridQueryCancel; @@ -2202,8 +2203,12 @@ public class IgniteH2Indexing implements GridQueryIndexing { catch (RuntimeException | Error e) { GridNearTxLocal tx; - if (mvccEnabled && (tx = tx(ctx)) != null) + if (mvccEnabled && (tx = tx(ctx)) != null && + (!(e instanceof IgniteSQLException) || /* Parsing errors should not rollback Tx. */ + ((IgniteSQLException)e).sqlState() != SqlStateCode.PARSING_EXCEPTION) ) { + tx.setRollbackOnly(); + } throw e; } http://git-wip-us.apache.org/repos/asf/ignite/blob/ac093b9e/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 053d370..b71dd26 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 @@ -50,6 +50,7 @@ import org.apache.ignite.internal.processors.cache.KeyCacheObject; import org.apache.ignite.internal.processors.cache.distributed.near.GridNearTxLocal; import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow; import org.apache.ignite.internal.processors.cache.persistence.CacheDataRowAdapter; +import org.apache.ignite.internal.processors.cache.query.IgniteQueryErrorCode; import org.apache.ignite.internal.processors.cache.query.SqlFieldsQueryEx; import org.apache.ignite.internal.processors.query.IgniteSQLException; import org.apache.ignite.internal.transactions.IgniteTxTimeoutCheckedException; @@ -237,6 +238,53 @@ public abstract class CacheMvccSqlTxQueriesAbstractTest extends CacheMvccAbstrac /** * @throws Exception If failed. */ + public void testParsingErrorHasNoSideEffect() throws Exception { + ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 0, 4) + .setIndexedTypes(Integer.class, Integer.class); + + IgniteEx node = startGrid(0); + + IgniteCache<Object, Object> cache = node.cache(DEFAULT_CACHE_NAME); + + try (Transaction tx = node.transactions().txStart(PESSIMISTIC, REPEATABLE_READ)) { + tx.timeout(TX_TIMEOUT); + + SqlFieldsQuery qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (1),(2,2),(3,3)"); + + try { + try (FieldsQueryCursor<List<?>> cur = cache.query(qry)) { + fail("We should not get there."); + } + } + catch (CacheException ex){ + IgniteSQLException cause = X.cause(ex, IgniteSQLException.class); + + assertNotNull(cause); + assertEquals(IgniteQueryErrorCode.PARSING, cause.statusCode()); + + assertFalse(tx.isRollbackOnly()); + } + + qry = new SqlFieldsQuery("INSERT INTO Integer (_key, _val) values (4,4),(5,5),(6,6)"); + + try (FieldsQueryCursor<List<?>> cur = cache.query(qry)) { + assertEquals(3L, cur.iterator().next().get(0)); + } + + tx.commit(); + } + + assertNull(cache.get(1)); + assertNull(cache.get(2)); + assertNull(cache.get(3)); + assertEquals(4, cache.get(4)); + assertEquals(5, cache.get(5)); + assertEquals(6, cache.get(6)); + } + + /** + * @throws Exception If failed. + */ public void testQueryInsertStaticCache() throws Exception { ccfg = cacheConfiguration(cacheMode(), FULL_SYNC, 2, DFLT_PARTITION_COUNT) .setIndexedTypes(Integer.class, Integer.class);