diff --git a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java index 30ee3d0..3d5142b 100755 --- a/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java +++ b/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBDocumentStore.java @@ -683,7 +683,7 @@ public class RDBDocumentStore implements DocumentStore { private Exception callStack; - private RDBConnectionHandler ch; + RDBConnectionHandler ch; // from options private Set tablesToBeDropped = new HashSet(); diff --git a/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBOddity.java b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBOddity.java new file mode 100644 index 0000000..06bb823 --- /dev/null +++ b/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/document/rdb/RDBOddity.java @@ -0,0 +1,157 @@ +/* + * 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.jackrabbit.oak.plugins.document.rdb; + +import static com.google.common.collect.ImmutableSet.of; +import static java.sql.Statement.SUCCESS_NO_INFO; +import static junitx.framework.Assert.assertNotEquals; +import static org.apache.jackrabbit.oak.plugins.document.DocumentStoreFixture.RDB_MSSQL; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; +import static org.junit.Assume.assumeFalse; +import static org.junit.Assume.assumeTrue; + +import java.sql.BatchUpdateException; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.HashSet; +import java.util.Set; + +import org.apache.jackrabbit.oak.plugins.document.AbstractDocumentStoreTest; +import org.apache.jackrabbit.oak.plugins.document.DocumentStoreFixture; +import org.junit.Before; +import org.junit.Test; + +public class RDBOddity extends AbstractDocumentStoreTest { + + private RDBConnectionHandler ch; + + public RDBOddity(DocumentStoreFixture dsf) { + super(dsf); + assumeTrue(ds instanceof RDBDocumentStore); + assumeFalse(dsf == RDB_MSSQL); + } + + @Before + public void init() throws SQLException { + if (ds instanceof RDBDocumentStore) { + ch = ((RDBDocumentStore) ds).ch; + Connection con = ch.getRWConnection(); + try { + Statement st = con.createStatement(); + st.execute("DELETE FROM dstest_NODES"); + con.commit(); + st.close(); + } finally { + con.close(); + } + } + } + + @Test + public void batchUpdateResult() throws SQLException { + Connection con = ch.getRWConnection(); + try { + Statement st = con.createStatement(); + st.execute("INSERT INTO dstest_NODES (id) VALUES ('key-3')"); + con.commit(); + st.close(); + + PreparedStatement batchSt = con.prepareStatement("UPDATE dstest_NODES SET data = 'xyz' WHERE id = ?"); + batchSt.setString(1, "key-1"); + batchSt.addBatch(); + + batchSt.setString(1, "key-2"); + batchSt.addBatch(); + + batchSt.setString(1, "key-3"); + batchSt.addBatch(); + + int[] batchResult = batchSt.executeBatch(); + batchSt.close(); + con.commit(); + + assertNotSuccess("Row doesn't exists, can't be updated.", batchResult[0]); + assertNotSuccess("Row doesn't exists, can't be updated.", batchResult[1]); + assertSuccess("Row should be updated correctly.", batchResult[2]); + } finally { + con.close(); + } + } + + @Test + public void batchFailingInsertResult() throws SQLException { + Connection con = ch.getRWConnection(); + try { + Statement st = con.createStatement(); + st.execute("INSERT INTO dstest_NODES (id) VALUES ('key-3')"); + con.commit(); + st.close(); + + PreparedStatement batchSt = con.prepareStatement("INSERT INTO dstest_NODES (id) VALUES (?)"); + batchSt.setString(1, "key-1"); + batchSt.addBatch(); + + batchSt.setString(1, "key-2"); + batchSt.addBatch(); + + batchSt.setString(1, "key-3"); + batchSt.addBatch(); + + int[] batchResult = null; + try { + batchSt.executeBatch(); + fail("Batch operation should fail"); + } catch (BatchUpdateException e) { + batchResult = e.getUpdateCounts(); + } + batchSt.close(); + con.commit(); + + assertSuccess("Row should be inserted correctly.", batchResult[0]); + assertSuccess("Row should be inserted correctly.", batchResult[1]); + if (batchResult.length == 3) { + assertNotSuccess("Row already exists, shouldn't be inserted.", batchResult[2]); + } + + st = con.createStatement(); + ResultSet results = st.executeQuery("SELECT id FROM dstest_NODES"); + Set ids = new HashSet(); + while (results.next()) { + ids.add(results.getString(1)); + } + results.close(); + st.close(); + assertEquals("Some of the rows weren't inserted.", of("key-1", "key-2", "key-3"), ids); + } finally { + con.close(); + } + } + + private static void assertSuccess(String message, int result) { + assertTrue(message, result == 1 || result == SUCCESS_NO_INFO); + } + + private static void assertNotSuccess(String message, int result) { + assertNotEquals(message, 1, result); + assertNotEquals(message, SUCCESS_NO_INFO, result); + } +} \ No newline at end of file