preStatement.executeUpdate("insert into APP.fooMorph values (3)");
preStatement.executeUpdate("insert into APP.fooMorph values (4)");
preStatement.close();
XADataSource xads = J2EEDataSource.getXADataSource();
XAConnection xac = xads.getXAConnection();
XAResource xar = xac.getXAResource();
Connection conn = xac.getConnection();
/*
* autocommit off; insert into foo values (1); select * from
* global_xactTable where gxid is not null order by gxid,username;
* commit;
*/
conn.setAutoCommit(false);
Statement s = conn.createStatement();
s.executeUpdate("insert into APP.fooMorph values (2001)");
// no rows expected
XATestUtil.checkXATransactionView(conn, null);
conn.commit();
/*
* autocommit on; insert into foo values (2); select * from
* global_xactTable where gxid is not null order by gxid,username;
*
*/
conn.setAutoCommit(true);
s.executeUpdate("insert into APP.fooMorph values (2002)");
XATestUtil.checkXATransactionView(conn, null);
/*
* -- morph the connection to a global transaction xa_start xa_noflags
* 1; select * from global_xactTable where gxid is not null order by
* gxid,username; insert into foo values (3);
*/
Xid xid = XATestUtil.getXid(1001, 66, 13);
xar.start(xid, XAResource.TMNOFLAGS);
String[][] expectedRows = { { "(1", "IDLE", "NULL", "APP",
"UserTransaction" } };
XATestUtil.checkXATransactionView(conn, expectedRows);
s.executeUpdate("insert into APP.fooMorph values (2003)");
/*
* -- disallowed commit; -- disallowed rollback; -- disallowed
* autocommit on; -- OK autocommit off;
*/
try {
conn.commit();
fail("FAIL: commit allowed in global xact");
} catch (SQLException e) {
}
try {
conn.rollback();
fail("FAIL: roll back allowed in global xact");
} catch (SQLException e) {
}
try {
conn.setAutoCommit(true);
fail("FAIL: setAutoCommit(true) allowed " + "in global xact");
} catch (SQLException e) {
}
try {
conn.setSavepoint();
fail("FAIL: setSavepoint() allowed in global xact");
} catch (SQLException e) {
}
try {
conn.setSavepoint("badsavepoint");
fail("FAIL: setSavepoint(String) allowed in " + "global xact");
} catch (SQLException e) {
}
conn.setAutoCommit(false);
// s was created in local mode so it has holdibilty
// set, will execute but ResultSet will have close on commit
// DERBY-1158 query with holdable statement
s.executeQuery("select * from APP.fooMorph where A >= 2000").close();
s.close();
// statement created in global xact is CLOSE_CURSORS_AT_COMMIT
s = conn.createStatement();
assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, s
.getResultSetHoldability());
/*
* select * from foo; xa_end xa_success 1; xa_prepare 1;
*/
ResultSet rs = s.executeQuery("select * from APP.fooMorph where A >= 2000");
expectedRows = new String[][] { { "2001" }, { "2002" }, { "2003" } };
rs.close();
xar.end(xid, XAResource.TMSUCCESS);
xar.prepare(xid);
/*
* -- dup id xa_start xa_noflags 1;
*/
try {
xar.start(xid, XAResource.TMNOFLAGS);
fail("FAIL - start with duplicate XID");
} catch (XAException e) {
if (e.errorCode != XAException.XAER_DUPID)
throw e;
}
/*
* xa_start xa_noflags 2; -- still should disallow autommit; autocommit
* on; -- still should disallow commit and rollback commit; rollback;
* select * from global_xactTable where gxid is not null order by
* gxid,username; xa_end xa_suspend 2;
*/
Xid xid2 = XATestUtil.getXid(1002, 23, 3);
xar.start(xid2, XAResource.TMNOFLAGS);
try {
conn.commit();
fail("FAIL: commit allowed in global xact");
} catch (SQLException e) {
}
try {
conn.rollback();
fail("FAIL: roll back allowed in global xact");
} catch (SQLException e) {
}
try {
conn.setAutoCommit(true);
fail("FAIL: setAutoCommit(true) allowed in global xact");
} catch (SQLException e) {
}
conn.setAutoCommit(false);
xar.end(xid2, XAResource.TMSUSPEND);
/*
* -- get local connection again xa_getconnection;
*
* insert into foo values (5); -- autocommit should be on by default;
* commit;
*
* autocommit off; insert into foo values (6); -- commit and rollback is
* allowed on local connection rollback;
*
* insert into foo values (6); commit;
*/
conn = xac.getConnection();
s = conn.createStatement();
s.executeUpdate("insert into APP.fooMorph values (2005)");
conn.commit();
conn.setAutoCommit(false);
s.executeUpdate("insert into APP.fooMorph values (2006)");
conn.rollback();
s.executeUpdate("insert into APP.fooMorph values (2007)");
conn.commit();
expectedRows = new String[][] {
{ "(1", "PREPARED", "false", "APP", "UserTransaction" },
{ "(1", "IDLE", "NULL", "APP", "UserTransaction" } };
XATestUtil.checkXATransactionView(conn, expectedRows);
/*
* -- I am still able to commit other global transactions while I am
* attached to a -- local transaction. xa_commit xa_2phase 1; xa_end
* xa_success 2; xa_rollback 2;
*/
xar.commit(xid, false);
xar.end(xid2, XAResource.TMSUCCESS);
xar.rollback(xid2);
XATestUtil.checkXATransactionView(conn, null);
rs = s.executeQuery("select * from APP.fooMorph where A >= 2000");
expectedRows = new String[][] { { "2001" }, { "2002" }, { "2003" },
{ "2005" }, { "2007" } };
JDBC.assertFullResultSet(rs, expectedRows);
rs.close();
conn.rollback();
conn.close();
/*
* xa_getconnection; select * from global_xactTable where gxid is not
* null order by gxid,username; select * from foo; autocommit off;
* delete from foo;
*/
conn = xac.getConnection();
conn.setAutoCommit(false);
s = conn.createStatement();
s.executeUpdate("delete from app.fooMorph");
rs = s.executeQuery("select * from APP.fooMorph");
JDBC.assertEmpty(rs);
rs.close();
/*
* -- yanking a local connection away should rollback the changes
*/
conn = xac.getConnection();
conn.setAutoCommit(false);
s = conn.createStatement();
rs = s.executeQuery("select * from APP.fooMorph where A >= 2000");
expectedRows = new String[][] { { "2001" }, { "2002" }, { "2003" },
{ "2005" }, { "2007" } };
JDBC.assertFullResultSet(rs, expectedRows);
/*
* -- cannot morph it if the local transaction is not idle xa_start
* xa_noflags 3; commit; -- now morph it to a global transaction
* xa_start xa_noflags 3;
*/
Xid xid3 = XATestUtil.getXid(1003, 27, 9);
try {
xar.start(xid3, XAResource.TMNOFLAGS);
fail("FAIL XAResource.start on a global transaction with an active local transaction (autocommit false)");
} catch (XAException xae) {
if (xae.errorCode != XAException.XAER_OUTSIDE)
throw xae;
}
conn.commit();
xar.start(xid3, XAResource.TMNOFLAGS);
/*
* -- now I shouldn't be able to yank it xa_getconnection;
*/
// DERBY-341 - client skip XAConnection with active local xact
if (usingEmbedded()) {
try {
xac.getConnection();
fail("FAIL: getConnection with active global xact");
} catch (SQLException sqle) {
assertSQLState("XJ059", sqle);
}
}
/*
* select * from foo; delete from foo;
*
* xa_end xa_fail 3; xa_rollback 3; -- local connection again
* xa_getconnection; select * from global_xactTable where gxid is not
* null order by gxid,username; select * from foo;
*/
s = conn.createStatement();
s.executeUpdate("delete from APP.fooMorph");
rs = s.executeQuery("select * from APP.fooMorph where A >= 2000");
JDBC.assertEmpty(rs);
rs.close();
try {
xar.end(xid3, XAResource.TMFAIL);
} catch (XAException e) {
if (e.errorCode != XAException.XA_RBROLLBACK)
throw e;
}
xar.rollback(xid3);
conn = xac.getConnection();
s = conn.createStatement();
rs = s.executeQuery("select * from APP.fooMorph where A >= 2000");
expectedRows = new String[][] { { "2001" }, { "2002" }, { "2003" },
{ "2005" }, { "2007" } };
JDBC.assertFullResultSet(rs, expectedRows);