|
7 | 7 | import static org.junit.Assert.assertNotNull;
|
8 | 8 | import static org.junit.Assume.assumeTrue;
|
9 | 9 | import static org.junit.jupiter.api.Assertions.assertArrayEquals;
|
10 |
| -import static org.junit.jupiter.api.Assertions.assertTrue; |
11 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals;
|
| 11 | +import static org.junit.jupiter.api.Assertions.assertTrue; |
12 | 12 | import static org.junit.jupiter.api.Assertions.fail;
|
13 | 13 |
|
14 | 14 | import java.lang.reflect.Field;
|
|
27 | 27 | import java.util.Calendar;
|
28 | 28 | import java.util.HashMap;
|
29 | 29 | import java.util.TimeZone;
|
| 30 | +import java.util.Timer; |
| 31 | +import java.util.TimerTask; |
| 32 | +import java.util.concurrent.CountDownLatch; |
| 33 | +import java.util.concurrent.ExecutorService; |
| 34 | +import java.util.concurrent.Executors; |
30 | 35 |
|
31 |
| -import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; |
32 | 36 | import org.junit.jupiter.api.AfterAll;
|
33 | 37 | import org.junit.jupiter.api.BeforeAll;
|
34 | 38 | import org.junit.jupiter.api.Tag;
|
|
39 | 43 |
|
40 | 44 | import com.microsoft.sqlserver.jdbc.RandomUtil;
|
41 | 45 | import com.microsoft.sqlserver.jdbc.SQLServerConnection;
|
| 46 | +import com.microsoft.sqlserver.jdbc.SQLServerPreparedStatement; |
42 | 47 | import com.microsoft.sqlserver.jdbc.SQLServerStatement;
|
43 | 48 | import com.microsoft.sqlserver.jdbc.TestResource;
|
44 | 49 | import com.microsoft.sqlserver.jdbc.TestUtils;
|
@@ -206,6 +211,82 @@ public void testSqlServerBulkCopyCachingConnectionLevel() throws Exception {
|
206 | 211 | }
|
207 | 212 | }
|
208 | 213 |
|
| 214 | + @Test |
| 215 | + public void testSqlServerBulkCopyCachingConnectionLevelMultiThreaded() throws Exception { |
| 216 | + // Needs to be on a JDK version greater than 8 |
| 217 | + assumeTrue(TestUtils.getJVMVersion() > 8); |
| 218 | + |
| 219 | + Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); |
| 220 | + long ms = 1578743412000L; |
| 221 | + long timeOut = 30000; |
| 222 | + int NUMBER_SIMULTANEOUS_INSERTS = 5; |
| 223 | + |
| 224 | + try (SQLServerConnection con = (SQLServerConnection) DriverManager.getConnection(connectionString |
| 225 | + + ";useBulkCopyForBatchInsert=true;cacheBulkCopyMetadata=true;sendTemporalDataTypesAsStringForBulkCopy=false;"); |
| 226 | + Statement stmt = con.createStatement()) { |
| 227 | + |
| 228 | + TestUtils.dropTableIfExists(timestampTable1, stmt); |
| 229 | + String createSqlTable1 = "CREATE TABLE " + timestampTable1 + " (c1 DATETIME2(3))"; |
| 230 | + stmt.execute(createSqlTable1); |
| 231 | + |
| 232 | + Field bulkcopyMetadataCacheField; |
| 233 | + |
| 234 | + if (con.getClass().getName().equals("com.microsoft.sqlserver.jdbc.SQLServerConnection43")) { |
| 235 | + bulkcopyMetadataCacheField = con.getClass().getSuperclass() |
| 236 | + .getDeclaredField("BULK_COPY_OPERATION_CACHE"); |
| 237 | + } else { |
| 238 | + bulkcopyMetadataCacheField = con.getClass().getDeclaredField("BULK_COPY_OPERATION_CACHE"); |
| 239 | + } |
| 240 | + |
| 241 | + bulkcopyMetadataCacheField.setAccessible(true); |
| 242 | + Object bulkcopyCache = bulkcopyMetadataCacheField.get(con); |
| 243 | + |
| 244 | + ((HashMap<?, ?>) bulkcopyCache).clear(); |
| 245 | + |
| 246 | + TimerTask task = new TimerTask() { |
| 247 | + public void run() { |
| 248 | + ((HashMap<?, ?>) bulkcopyCache).clear(); |
| 249 | + fail(TestResource.getResource("R_executionTooLong")); |
| 250 | + } |
| 251 | + }; |
| 252 | + Timer timer = new Timer("Timer"); |
| 253 | + timer.schedule(task, timeOut); // Run a timer to help us exit if we get deadlocked |
| 254 | + |
| 255 | + final CountDownLatch countDownLatch = new CountDownLatch(NUMBER_SIMULTANEOUS_INSERTS); |
| 256 | + Runnable runnable = () -> { |
| 257 | + try { |
| 258 | + for (int i = 0; i < 5; ++i) { |
| 259 | + PreparedStatement preparedStatement = con |
| 260 | + .prepareStatement("INSERT INTO " + timestampTable1 + " VALUES(?)"); |
| 261 | + Timestamp timestamp = new Timestamp(ms); |
| 262 | + preparedStatement.setTimestamp(1, timestamp, gmtCal); |
| 263 | + preparedStatement.addBatch(); |
| 264 | + preparedStatement.executeBatch(); |
| 265 | + } |
| 266 | + countDownLatch.countDown(); |
| 267 | + countDownLatch.await(); |
| 268 | + } catch (Exception e) { |
| 269 | + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); |
| 270 | + } finally { |
| 271 | + ((HashMap<?, ?>) bulkcopyCache).clear(); |
| 272 | + } |
| 273 | + }; |
| 274 | + |
| 275 | + ExecutorService executor = Executors.newFixedThreadPool(NUMBER_SIMULTANEOUS_INSERTS); |
| 276 | + |
| 277 | + try { |
| 278 | + for (int i = 0; i < NUMBER_SIMULTANEOUS_INSERTS; i++) { |
| 279 | + executor.submit(runnable); |
| 280 | + } |
| 281 | + executor.shutdown(); |
| 282 | + } catch (Exception e) { |
| 283 | + fail(TestResource.getResource("R_unexpectedException") + e.getMessage()); |
| 284 | + } finally { |
| 285 | + ((HashMap<?, ?>) bulkcopyCache).clear(); |
| 286 | + } |
| 287 | + } |
| 288 | + } |
| 289 | + |
209 | 290 | @Test
|
210 | 291 | public void testValidTimezoneForTimestampBatchInsertWithBulkCopy() throws Exception {
|
211 | 292 | Calendar gmtCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
|
|
0 commit comments