private void testMergePartitioned(boolean causeConflict, boolean sharedWrite) throws Exception {
    dropTable(new String[] {"target","source"});
    conf.setBoolVar(HiveConf.ConfVars.TXN_WRITE_X_LOCK, !sharedWrite);

    driver.run("create table target (a int, b int) " +
        "partitioned by (p int, q int) clustered by (a) into 2  buckets " +
        "stored as orc TBLPROPERTIES ('transactional'='true')");
    driver.run("insert into target partition(p,q) values (1,2,1,2), (3,4,1,2), (5,6,1,3), (7,8,2,2)");
    driver.run("create table source (a1 int, b1 int, p1 int, q1 int)");

    driver.compileAndRespond("update target set b = 2 where p=1", true);
    long txnId1 = txnMgr.getCurrentTxnId();
    txnMgr.acquireLocks(driver.getPlan(), ctx, "T1");
    List<ShowLocksResponseElement> locks = getLocks();
    Assert.assertEquals("Unexpected lock count", 3, locks.size());

    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=2", locks);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=3", locks);

    DbTxnManager txnMgr2 = (DbTxnManager) TxnManagerFactory.getTxnManagerFactory().getTxnManager(conf);
    swapTxnManager(txnMgr2);
    //start a 2nd (overlapping) txn
    driver.compileAndRespond("merge into target using source " +
        "on target.p=source.p1 and target.a=source.a1 " +
        "when matched then update set b = 11 " +
        "when not matched then insert values(a1,b1,p1,q1)", true);
    long txnid2 = txnMgr2.getCurrentTxnId();
    txnMgr2.acquireLocks(driver.getPlan(), ctx, "T2", false);
    locks = getLocks(txnMgr);
    Assert.assertEquals("Unexpected lock count", 8, locks.size());
    /*
     * W locks from T1 are still there, so all locks from T2 block.
     * The Update part of Merge requests W locks for each existing partition in target.
     * The Insert part doesn't know which partitions may be written to: thus R lock on target table.
     */
    TestTxnDbUtil.checkLock(LockType.SHARED_READ, (sharedWrite ? LockState.ACQUIRED : LockState.WAITING),
        "default", "source", null, locks);
    long extLockId = TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.SHARED_READ),
        (sharedWrite ? LockState.ACQUIRED : LockState.WAITING),
        "default", "target", null, locks, sharedWrite).getLockid();

    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        (sharedWrite ? LockState.ACQUIRED : LockState.WAITING),
        "default", "target", "p=1/q=2", locks, sharedWrite);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=2", locks);

    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        (sharedWrite ? LockState.ACQUIRED : LockState.WAITING),
        "default", "target", "p=1/q=3", locks, sharedWrite);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=3", locks);

    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        (sharedWrite ? LockState.ACQUIRED : LockState.WAITING),
        "default", "target", "p=2/q=2", locks);

    Assert.assertEquals(
        "TXN_COMPONENTS mismatch(" + JavaUtils.txnIdToString(txnId1) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"TXN_COMPONENTS\""),
        1, //because it's using a DP write
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"TXN_COMPONENTS\" where \"TC_TXNID\"=" + txnId1));

    //complete T1 transaction (simulate writing to 2 partitions)
    long writeId = txnMgr.getTableWriteId("default", "target");
    AddDynamicPartitions adp = new AddDynamicPartitions(txnId1, writeId, "default", "target",
        Arrays.asList("p=1/q=2", "p=1/q=3"));
    adp.setOperationType(DataOperationType.UPDATE);
    txnHandler.addDynamicPartitions(adp);
    Assert.assertEquals(
        "TXN_COMPONENTS mismatch(" + JavaUtils.txnIdToString(txnId1) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"TXN_COMPONENTS\""),
        2,
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"TXN_COMPONENTS\" where \"TC_TXNID\"=" + txnId1 +
            " and \"TC_OPERATION_TYPE\"='u'"));

    txnMgr.commitTxn(); //commit T1
    Assert.assertEquals("WRITE_SET mismatch(" + JavaUtils.txnIdToString(txnId1) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"WRITE_SET\""),
        2, //2 partitions updated
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"WRITE_SET\" where \"WS_TXNID\"=" + txnId1 +
            " and \"WS_OPERATION_TYPE\"='u'"));

    //re-check locks which were in Waiting state - should now be Acquired
    ((DbLockManager)txnMgr2.getLockManager()).checkLock(extLockId);
    locks = getLocks();
    Assert.assertEquals("Unexpected lock count", 5, locks.size());

    TestTxnDbUtil.checkLock(LockType.SHARED_READ, LockState.ACQUIRED, "default", "source", null, locks);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.SHARED_READ),
        LockState.ACQUIRED, "default", "target", null, locks);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=2", locks);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=1/q=3", locks);
    TestTxnDbUtil.checkLock((sharedWrite ? LockType.SHARED_WRITE : LockType.EXCL_WRITE),
        LockState.ACQUIRED, "default", "target", "p=2/q=2", locks);

    Assert.assertEquals(
        "TXN_COMPONENTS mismatch(" + JavaUtils.txnIdToString(txnid2) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"TXN_COMPONENTS\""),
        1, //because it's using a DP write
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"TXN_COMPONENTS\" where \"TC_TXNID\"=" + txnid2));

    //complete T2 txn
    //simulate Insert into 2 partitions
    writeId = txnMgr2.getTableWriteId("default", "target");
    adp = new AddDynamicPartitions(txnid2, writeId, "default", "target",
        Arrays.asList("p=1/q=2", "p=1/q=3"));
    adp.setOperationType(DataOperationType.INSERT);
    txnHandler.addDynamicPartitions(adp);
    Assert.assertEquals(
        "TXN_COMPONENTS mismatch(" + JavaUtils.txnIdToString(txnid2) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"TXN_COMPONENTS\""),
        2,
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"TXN_COMPONENTS\" where \"TC_TXNID\"=" + txnid2 +
            " and \"TC_OPERATION_TYPE\"='i'"));
    //simulate Update of 1 partitions; depending on causeConflict, choose one of the partitions
    //which was modified by the T1 update stmt or choose a non-conflicting one
    adp = new AddDynamicPartitions(txnid2, writeId, "default", "target",
        Collections.singletonList(causeConflict ? "p=1/q=2" : "p=1/q=1"));
    adp.setOperationType(DataOperationType.UPDATE);
    txnHandler.addDynamicPartitions(adp);
    Assert.assertEquals(
        "TXN_COMPONENTS mismatch(" + JavaUtils.txnIdToString(txnid2) + "): " +
        TestTxnDbUtil.queryToString(conf, "select * from \"TXN_COMPONENTS\""),
        1,
        TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"TXN_COMPONENTS\" where \"TC_TXNID\"=" + txnid2 +
            " and \"TC_OPERATION_TYPE\"='u'"));

    LockException expectedException = null;
    try {
      txnMgr2.commitTxn();
    }
    catch (LockException e) {
      expectedException = e;
    }
    if (causeConflict && sharedWrite) {
      Assert.assertNotNull("Didn't get exception", expectedException);
      Assert.assertEquals("Got wrong message code", ErrorMsg.TXN_ABORTED, expectedException.getCanonicalErrorMsg());
      Assert.assertEquals("Exception msg didn't match",
          "Aborting [txnid:4,4] due to a write conflict on default/target/p=1/q=2 committed by [txnid:3,4] u/u",
          expectedException.getCause().getMessage());
    } else {
      Assert.assertEquals("WRITE_SET mismatch(" + JavaUtils.txnIdToString(txnid2) + "): " +
          TestTxnDbUtil.queryToString(conf, "select * from \"WRITE_SET\""),
          1, //1 partitions updated
          TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"WRITE_SET\" where \"WS_TXNID\"=" + txnid2 +
              " and \"WS_OPERATION_TYPE\"='u'"));
      Assert.assertEquals("WRITE_SET mismatch(" + JavaUtils.txnIdToString(txnid2) + "): " +
          TestTxnDbUtil.queryToString(conf, "select * from \"WRITE_SET\""),
          1, //1 partitions updated (and no other entries)
          TestTxnDbUtil.countQueryAgent(conf, "select count(*) from \"WRITE_SET\" where \"WS_TXNID\"=" + txnid2));
    }
    dropTable(new String[] {"target","source"});
  }
"run" an Update and Merge concurrently; Check that correct locks are acquired.
Check state of auxiliary ACID tables.
@param causeConflict - true to make the operations cause a Write conflict
ql/src/test/org/apache/hadoop/hive/ql/lockmgr/TestDbTxnManager2.java